我使用MVVM并遇到以下问题。我的TextBox.Text与UpdateSourceTrigger = LostFocus绑定(这就是用户想要的)。我有一个带SaveCommand CommandBinding的按钮 - 这个工作。现在我有一个Strg + S的KeyBinding,它也执行SaveCommand。这就是问题所在:当我在文本框中并按下Strg + s时,更改不在viewmodel中。
有没有办法让KeyBinding的MVVM命令和TextBox的UpdateSourceTrigger = LostFocus一起工作?
检查问题的一些代码
<Window>
<Window.InputBindings>
<KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveCommand}"></KeyBinding>
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding MyText1, UpdateSourceTrigger=LostFocus}" Width="100"></TextBox>
<Button Grid.Row="1" Content="_Save" Command="{Binding SaveCommand}" IsDefault="True"></Button>
</Grid>
</Window>
public partial class MainWindow : Window
{
private Viewmodel _data;
public MainWindow()
{
_data = new Viewmodel();
InitializeComponent();
this.DataContext = _data;
}
}
public class Viewmodel : INPCBase
{
private string _myText1;
private Lazy<DelegateCommand> _save;
public Viewmodel()
{
this._save = new Lazy<DelegateCommand>(()=> new DelegateCommand(this.SaveCommandExecute));
}
private void SaveCommandExecute()
{
MessageBox.Show(MyText1);
}
public string MyText1
{
get { return _myText1; }
set { _myText1 = value; this.NotifyPropertyChanged(()=>MyText1);}
}
public ICommand SaveCommand
{
get { return _save.Value; }
}
}
答案 0 :(得分:1)
目前我提出了以下解决方法。在我定义我的KeyBindings的usercontrol / views中,我也会监听PreviewKeyDown事件并将焦点设置为例如下一个元素。 Strg + S被按下了。
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.S && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
{
var fe = Keyboard.FocusedElement as UIElement;
if (fe != null)
{
fe.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
}
答案 1 :(得分:0)
我遇到了同样的问题,最终得到了TextBox的附加属性。
public static bool GetCommitOnSave(DependencyObject obj)
{
return (bool)obj.GetValue(CommitOnSaveProperty);
}
public static void SetCommitOnSave(DependencyObject obj, bool value)
{
obj.SetValue(CommitOnSaveProperty, value);
}
public static readonly DependencyProperty CommitOnSaveProperty =
DependencyProperty.RegisterAttached("CommitOnSave", typeof(bool), typeof(Helper), new PropertyMetadata(false, CommitOnSavePropertyChanged));
private static void CommitOnSavePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox textBox)
{
if ((bool)e.NewValue)
{
if ((bool)e.NewValue)
{
textBox.KeyDown += TextBox_KeyDown;
}
else
{
textBox.KeyDown -= TextBox_KeyDown;
}
}
}
}
private static void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var textBox = (TextBox)sender;
if (e.Key == Key.S && Keyboard.Modifiers == ModifierKeys.Control)
{
BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty).UpdateSource();
}
}
使用<TextBox Text="{Binding Name}" local:Helper.CommitOnSave="True" />
当然,您可以为表单中的所有TextBox设置样式的附加属性。
答案 2 :(得分:0)
我想我找到了最适合我的解决方案。我使用附加属性混合解决方案@blindmeis和我之前的解决方案。
我创建了更新实际键盘聚焦元素的绑定源的命令:
public class CommitValueCommand : ICommand
{
private static CommitValueCommand _instance;
public static CommitValueCommand Command => _instance ?? (_instance = new CommitValueCommand());
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
if (Keyboard.FocusedElement is TextBox textBox)
{
BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty).UpdateSource();
}
//for combobox etc.
else if (Keyboard.FocusedElement is Selector selector)
{
BindingOperations.GetBindingExpression(selector, Selector.SelectedValueProperty).UpdateSource();
}
}
}
在命令SaveCommand的Execute
方法中,刚开始调用CommitValueCommand.Command.Execute()
。