2012-03-13 17 views
0

ComboBox一個SourceUpdated綁定操作:撤消上一個ComboBox

<ComboBox 
    SourceUpdated="MyComboBox_SourceUpdated" 
    ItemsSource="{Binding ...}" 
    SelectedValue="{Binding Path=SelectedValueMember, NotifyOnSourceUpdated=True}" 
    SelectedValuePath="..." 
    DisplayMemberPath="..." 
/> 

而且我SourceUpdated處理程序:

private void MyComboBox_SourceUpdated(object sender, DataTransferEventArgs args) { 
    if (/* user answers no to an 'are you sure?' prompt */) { 
     // TODO: revert ComboBox back to original value 
    } 
} 

我有難以恢復的組合框回到其原始值(在「 TODO「評論我上面的代碼)。

我想是簡單地改回在DataContext的SelectedValueMember的價值,假設第一和最明顯的東西結合將更新組合框:

MyDataContext.SelectedValueMember = original_value; 

當我做到這一點,在調試器我可以看到它確實正在更新SelectedValueMember值,但ComboBox不會變回 - 它保留在新值上。

任何想法?


AngelWPF的回答下面的作品,並可能是最整潔和清晰的方式。

我也不過,找到一個非顯而易見的解決方案:只需通過將操作的第二UI線程通過BeginInvoke手段

private void MyComboBox_SourceUpdated(object sender, DataTransferEventArgs args) { 
    if (/* user answers no to an 'are you sure?' prompt */) { 
     Dispatcher.BeginInvoke(new Action(() => { 
      MyDataContext.SelectedValueMember = original_value; 
     })); 
    } 
} 

,它的作品!我可能是錯的,但我的直覺是爲了避免綁定更新循環,直接在源/目標更新處理程序中的操作不會被綁定反應。

+0

您是否在SelectedValueMember上提升'PropertyChanged'?或者它是一個'DependencyProperty'。 – Silvermind 2012-03-13 14:33:32

+0

Yep一個PropertyChanged事件引發。如果我測試並連接一個簡單的按鈕,其唯一目的是更改MyDataContext.SelectedValueMember的值,那麼源目標綁定工作正常,ComboBox更新。 – Ross 2012-03-13 14:41:09

+0

這裏有一個類似的問題和答案:http://stackoverflow.com/questions/2585183/wpf-combobox-selecteditem-change-to-previous-value/2709931#2709931。我認爲Angel的答案可能是最好的,但如果你不想在綁定上使用顯式模式,那麼使用BeginInvoke也可以。 – NathanAW 2012-03-13 15:43:44

回答

2

對於源的在綁定明確條件更新,使用updatesource觸發作爲顯式和處理組合框的選擇改變的事件與基於消息框結果的源中執行同步。

<StackPanel DataContext="{StaticResource MyObject}"> 
     <ComboBox ItemsSource="{Binding MyData}" 
      DisplayMemberPath="Name" 
      SelectedValuePath="ID" 
      SelectedValue="{Binding Path=MyID, 
            Mode=TwoWay, 
            UpdateSourceTrigger=Explicit}" 
      SelectionChanged="ComboBox_SelectionChanged"> 
     </ComboBox> 
     <TextBlock Text="{Binding Path=MyID}"/> 
    </StackPanel> 

所以ComboBox結合於具有NameID作爲性質的項的集合(稱爲MyData)。 ComboBox的選定值綁定到另一個名爲MyID的屬性。現在請注意UpdateSourceTrigger=ExplicitSelectedValue的綁定。

我同步的MyID的方式,當所述選擇的變化,與僅當用戶選擇如下面一個消息框Yes組合框的設定值...

private void ComboBox_SelectionChanged 
     (object sender, SelectionChangedEventArgs e) 
    { 
     var bndExp 
      = BindingOperations.GetBindingExpression(
       (ComboBox) sender, Selector.SelectedValueProperty); 
     if (bndExp != null && bndExp.ParentBinding != null) 
     { 
      if (MessageBox.Show(
        "Are you sure?", 
        "Sure?", 
        MessageBoxButton.YesNo) == MessageBoxResult.Yes) 
      { 
       ((MyObject) bndExp.DataItem).MyID 
        = (int)((ComboBox) sender).SelectedValue; 
      } 
     } 
    } 

Thsi方式沒有必要對還原。源明確更新,並且您可以完全控制它。

3

使用UpdateSourceTrigger =「明確的」添加到AngelWPF的回答是:

稍微清潔的方式做到這一點是使用了BindingExpression.UpdateSource()和BindingExpression.UpdateTarget()方法。 UpdateSource()將UI控件的值移動到ViewModel,並且UpdateTarget()以相反的方向移動數據。使用這些方法不必做這行的代碼爲您節省:

((MyObject) bndExp.DataItem).MyID = (int)((ComboBox) sender).SelectedValue; 

出乎AngelWPF的經驗,在我的情況我有恢復的組合框回到原來的值時,用戶即使我取消將Binding.UpdateSourceTrigger設置爲Explicit。也許這是因爲Telerik RadComboBox或者之前的評論不正確,我現在不能說。但以下任何一種方式,更易於閱讀,代碼工作。

private void OfficeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    var comboBox = (RadComboBox) sender; 
    var binding = comboBox.GetBindingExpression(RadComboBox.SelectedValueProperty); 

    if(MessageBox.Show("Are you sure?", "Are you sure?", MessageBoxButton.YesNo) == MessageBoxResult.Yes) 
    { 
     binding.UpdateSource(); 
    } 
    else 
    { 
     binding.UpdateTarget(); 
    } 
} 

根據需要添加您自己的空檢查。