有沒有辦法在觸發命令之前或之後更新綁定?我有一些文本字段可以使用命令進行編輯和保存,可通過鍵盤快捷方式訪問。由於綁定通常只在文本字段失去焦點時更新,因此按下鍵保存數據時不會保留最後的更改。相反,我必須首先從文本字段中刪除它,然後保存它。觸發命令時強制綁定更新
有沒有辦法以優雅的方式強制更新?我正在使用MVVM(但不是任何MVVM框架),所以我想讓UI特定的東西脫離命令代碼。另外,我並不想更改每次更改的綁定更新,只有在焦點丟失時才更新綁定即可。
有沒有辦法在觸發命令之前或之後更新綁定?我有一些文本字段可以使用命令進行編輯和保存,可通過鍵盤快捷方式訪問。由於綁定通常只在文本字段失去焦點時更新,因此按下鍵保存數據時不會保留最後的更改。相反,我必須首先從文本字段中刪除它,然後保存它。觸發命令時強制綁定更新
有沒有辦法以優雅的方式強制更新?我正在使用MVVM(但不是任何MVVM框架),所以我想讓UI特定的東西脫離命令代碼。另外,我並不想更改每次更改的綁定更新,只有在焦點丟失時才更新綁定即可。
我已經要求值之前明確地將焦點設置到其他一些元素現在解決了這個。這顯然使得當前具有焦點的元素失去它並更新綁定。
爲了確定重點,我寫了一個附加的屬性,受其他問題的答案啓發。此外,與my other question一起,我做了這個有點自動化。
所以使用它,我基本上是我的財產附加到一個元素,在這種情況下,標籤控件:
<TabControl c:Util.ShouldFocus="{Binding ShouldClearFocus}">
在我看來模型中,我有一個簡單的布爾屬性ShouldClearFocus
這是一個標準的屬性提升一個PropertyChangedEvent
,所以數據綁定的作品。然後,當我想重置焦點時,我簡單地將ShouldClearFocus
設置爲true
。附加屬性自動設置焦點並重新設置屬性值。這樣我可以繼續設置ShouldClearFocus
而不必將其設置爲false
。
的附加屬性是一個標準的實施與此爲其更改處理函數:
public static void ShouldFocusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(bool)e.NewValue || !(obj is FrameworkElement))
return;
FrameworkElement element = (FrameworkElement)obj;
if (element.Focusable)
element.Focus();
// reset value
BindingExpression bindingExpression = BindingOperations.GetBindingExpression(obj, ShouldFocusProperty);
if (bindingExpression != null)
{
PropertyInfo property = bindingExpression.DataItem.GetType().GetProperty(bindingExpression.ParentBinding.Path.Path);
if (property != null)
property.SetValue(bindingExpression.DataItem, false, null);
}
else
SetShouldFocus(obj, false);
}
下面是我用了類似的情況類:
public class TextBoxUpdatesTextBindingOnPropertyChanged : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += TextBox_TextChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.TextChanged -= TextBox_TextChanged;
}
void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var bindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
bindingExpression.UpdateSource();
}
}
XAML:
<TextBox Text="{Binding UserName,Mode=TwoWay,UpdateSourceTrigger=Explicit}">
<i:Interaction.Behaviors>
<h:TextBoxUpdatesTextBindingOnPropertyChanged />
</i:Interaction.Behaviors>
</TextBox>
調用OnPropertyChanged("YourPropertyName")
將提醒更新限值的視圖。
否則檢查出這個答案:WPF TextBox DataBind on EnterKey press。
我在我的項目中使用以下內容。問題是按鈕沒有收到焦點。
在我app.xaml.cs
EventManager.RegisterClassHandler(typeof(Button), ButtonBase.ClickEvent, new RoutedEventHandler(ButtonClick));
private void ButtonClick(object sender, RoutedEventArgs e)
{
if (sender != null && sender is Button)
{
(sender as Button).Focus();
}
}
該解決方案看起來可以接受,但我沒有一個按鈕被點擊。該命令由「KeyBinding」調用。 – poke
而不是改變焦點,如果當前元素是一個TextBox
你也可以只更新綁定源。你可以爲其他控件做類似的事情,但根據我的經驗,我只有TextBox
這個問題。
// if the current focused element is textbox then updates the source.
var focusedElement = Keyboard.FocusedElement as FrameworkElement;
if (focusedElement is TextBox)
{
var expression = focusedElement.GetBindingExpression(TextBox.TextProperty);
if (expression != null) expression.UpdateSource();
}
好主意,你會在MVVM設置中放哪個? - 也不知道在綁定表達式上實際上有一個'UpdateSource'方法,謝謝! – poke
我想你必須把它放在你的附屬物中 - 只是認爲這是對推進焦點的改進。你也可以使用類似於企業庫中的CompositeCommand來處理這個功能,但這取決於你的應用程序的結構。 –
我認爲要做到這一點的最好辦法是設置綁定的UpdateSourceTrigger=PropertyChanged
,然後用Reactive Extensions
節流事件流。通過這種方式,只有在用戶停止輸入一段時間後纔會更新該屬性(每秒1/2秒是一個很好的數量)。
這太好了,因爲該屬性不會一直更新,但它也會更新,而無需重點更改。正是你想要的。
Here is some really useful information on Rx
有具有可綁定IObservables here的MVVM擴展庫。他們在這裏的例子就是我所說的。
你問了優雅:在這裏。而且它也沒那麼多功夫。
在您的TextBox
上,您需要在文本綁定上設置UpdateSourceTrigger
,該文本綁定定義了何時使用文本框值更新源文件。默認情況下,它的LostFocus
爲Text
屬性,這正是發生了什麼 - 它只在失去焦點時更新源。您應該將UpdateSourceTrigger
的值設置爲PropertyChanged
,並且每次文本框值發生更改時它都會更新。
例如使用綁定命令的時候,所以上面的等於Path=Foo
從問題:*「我也不想改變綁定更新每個變化」*。 – poke
有很多在這裏靈活/優雅的事情
<TextBox ... Text="{Binding Foo, UpdateSourceTrigger=PropertyChanged}"/>
路徑是默認屬性。 我正在使用控件Name和CommandParameter屬性來解決此問題。
我新的WPF,所以讓我知道,如果我不這樣做事情的正確方式;)
XAML:
<dxc:SimpleButton Name="okButton" Content="OK" Command="{Binding OKCommand}" CommandParameter="{Binding ElementName=okButton}" IsDefault="True" Width="100"/>
C#:
private void OnOKCommand(object obj)
{
((System.Windows.FrameworkElement)obj).Focus();
// other code here
}
迄今爲止,在這個論壇上提出的最靈活/最優雅的解決方案。工作很好 - 謝謝 – BCA