2012-06-18 65 views
8

有沒有辦法在觸發命令之前或之後更新綁定?我有一些文本字段可以使用命令進行編輯和保存,可通過鍵盤快捷方式訪問。由於綁定通常只在文本字段失去焦點時更新,因此按下鍵保存數據時不會保留最後的更改。相反,我必須首先從文本字段中刪除它,然後保存它。觸發命令時強制綁定更新

有沒有辦法以優雅的方式強制更新?我正在使用MVVM(但不是任何MVVM框架),所以我想讓UI特定的東西脫離命令代碼。另外,我並不想更改每次更改的綁定更新,只有在焦點丟失時才更新綁定即可。

回答

2

我已經要求值之前明確地將焦點設置到其他一些元素現在解決了這個。這顯然使得當前具有焦點的元素失去它並更新綁定。

爲了確定重點,我寫了一個附加的屬性,受其他問題的答案啓發。此外,與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); 
} 
+0

迄今爲止,在這個論壇上提出的最靈活/最優雅的解決方案。工作很好 - 謝謝 – BCA

2

下面是我用了類似的情況類:

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

+0

問題是不是從數據→視圖的綁定,這是相反的方式。我想強制更新數據端。 – poke

+0

好吧,我發佈的鏈接顯示瞭如何創建一個行爲,當在控件上引發某個事件時,該行爲將更新綁定(在數據端)。如果你將它連接到KeyPressed或KeyUp事件,你應該得到你需要的效果。 –

+0

該解決方案包括將'UpdateSourceTrigger'設置爲'PropertyChanged',它應該已經夠用了,但如問題中所述,不是我想要的。我正在尋找一種方法來做到這一點,而無需更改觸發器。 – poke

0

我在我的項目中使用以下內容。問題是按鈕沒有收到焦點。

在我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(); 
     } 
    } 
+0

該解決方案看起來可以接受,但我沒有一個按鈕被點擊。該命令由「KeyBinding」調用。 – poke

9

而不是改變焦點,如果當前元素是一個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(); 
} 
+0

好主意,你會在MVVM設置中放哪個? - 也不知道在綁定表達式上實際上有一個'UpdateSource'方法,謝謝! – poke

+0

我想你必須把它放在你的附屬物中 - 只是認爲這是對推進焦點的改進。你也可以使用類似於企業庫中的CompositeCommand來處理這個功能,但這取決於你的應用程序的結構。 –

0

我認爲要做到這一點的最好辦法是設置綁定的UpdateSourceTrigger=PropertyChanged,然後用Reactive Extensions節流事件流。通過這種方式,只有在用戶停止輸入一段時間後纔會更新該屬性(每秒1/2秒是一個很好的數量)。

這太好了,因爲該屬性不會一直更新,但它也會更新,而無需重點更改。正是你想要的。

Here is some really useful information on Rx

有具有可綁定IObservables here的MVVM擴展庫。他們在這裏的例子就是我所說的。

你問了優雅:在這裏。而且它也沒那麼多功夫。

3

在您的TextBox上,您需要在文本綁定上設置UpdateSourceTrigger,該文本綁定定義了何時使用文本框值更新源文件。默認情況下,它的LostFocusText屬性,這正是發生了什麼 - 它只在失去焦點時更新源。您應該將UpdateSourceTrigger的值設置爲PropertyChanged,並且每次文本框值發生更改時它都會更新。

例如使用綁定命令的時候,所以上面的等於Path=Foo

+0

從問題:*「我也不想改變綁定更新每個變化」*。 – poke

0

有很多在這裏靈活/優雅的事情

<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 
    }