【问题标题】:Confirm with user before updating bound property change if dirty如果脏,在更新绑定属性更改之前与用户确认
【发布时间】:2014-10-03 16:35:30
【问题描述】:

我有一个下拉框,可以更改屏幕上显示的内容。如果 IsDirty 变量为真,我想要一个弹出窗口来通知用户如果他们尝试更改下拉菜单存在未保存的更改。

下拉列表绑定到属性,我尝试将消息框放入属性集中的尝试效果不佳。似乎每次我尝试拦截机会并对其进行修改时,结果都是该属性上的设置再次触发。

我尝试了一些我在网上找到的解决方案,但没有成功,有人有什么建议吗?

我最近的尝试是附加一个行为,但它有多次触发的相同问题,并且值已经改变了。

我正在使用 .net 4.5

 public class CancellableSelectionBehavior : Behavior<ComboBox>
    {

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectionChanged += OnSelectionChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.SelectionChanged -= OnSelectionChanged;
    }

    #region Properties

    #region IsDirtyCheck

    public static readonly DependencyProperty IsDirtyCheckProperty =
        DependencyProperty.Register(
            Reflection.GetPropertyName<CancellableSelectionBehavior>(m => m.IsDirtyCheck),
            typeof(bool),
            typeof(CancellableSelectionBehavior));

    public bool IsDirtyCheck
    {
        get { return (bool)GetValue(IsDirtyCheckProperty); }
        set { SetValue(IsDirtyCheckProperty, value); }
    }

    #endregion

    #region Selected Value

    public static readonly DependencyProperty SelectedValueProperty =
        DependencyProperty.Register(Reflection.GetPropertyName<CancellableSelectionBehavior>(m => m.SelectedValue),
                                    typeof(object), typeof(CancellableSelectionBehavior),
                                    new FrameworkPropertyMetadata(null,
                                                                  FrameworkPropertyMetadataOptions
                                                                      .BindsTwoWayByDefault, OnSelectedItemChanged));

    public object SelectedValue
    {
        get { return GetValue(SelectedValueProperty); }
        set { SetValue(SelectedValueProperty, value); }
    }

    #endregion

    #endregion

    private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = (CancellableSelectionBehavior)d;
        var selector = behavior.AssociatedObject;

        if (e.OldValue != null)
        {
            if (e.OldValue != e.NewValue)
            {
                if (behavior.IsDirtyCheck)
                {
                    string message = string.Format(UserMessages.UnSavedFaultPlygon, Environment.NewLine);
                    if (ServiceLocationContext.ServiceFinder.GetService<IMessageBox>()
                                              .Show(new MessageDialogOptions(message,
                                                                             UserMessages
                                                                                 .FaultPlygons,
                                                                             MessageDialogIcon
                                                                                 .Exclamation,
                                                                             MessageDialogButtons
                                                                                 .YesNo)) == MessageDialogResult.Yes)
                    {
                        selector.SelectedValue = e.NewValue;
                    }
                    else
                    {
                        selector.SelectedValue = e.OldValue;
                    }
                }
                else
                {
                    selector.SelectedValue = e.NewValue;
                }
            }
        }
    }

    /// <summary>
    /// Called when the associated selector's selection is changed.
    /// Tries to assign it to the <see cref="SelectedItem"/> property.
    /// If it fails, updates the selector's with  <see cref="SelectedItem"/> property's current value.
    /// </summary>
    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if ((e.AddedItems == null || e.AddedItems.Count == 0)) return;
        SelectedValue = AssociatedObject.SelectedValue;
    }

}





<ribbonDropDown:RibbonDropDownListView
                            Label="{Binding Path=MapModel.SelectedPostingItemName}"
                            Image="{Binding Path=LargeImageSource, ElementName=_postingTypeMenuButton}" 
                            Width="100"
                            ItemsSource="{Binding Path=MapModel.PostingHorizonItems}"                            
                            SelectedValuePath="Key"
                            Visibility="{Binding Path=MapModel.SelectedTypeKey, Converter={StaticResource EnumMatchToVisibilityConverter}, ConverterParameter={x:Static map2:MapPostingType.Horizon}}"
                            ToolTip="{Binding Path=MapModel.SelectedPostingItemDescription}">
                            <i:Interaction.Behaviors>
                                <common:CancellableSelectionBehavior IsDirtyCheck="{Binding Path=MapControlViewModel.IsFaultPolygonDirty}"
                                                                     SelectedValue="{Binding Path=MapModel.SelectedHorizonPostingItem}"/>
                            </i:Interaction.Behaviors>

【问题讨论】:

    标签: c# .net wpf mvvm


    【解决方案1】:

    我可能过于简化了答案,但我认为问题在于您正在捕获 onselectionchanged 事件,然后更改该代码块内的选择。

    这种行为看起来很整洁,但我认为你必须不基于这种事件来连接它。

    我会这样解决问题。 (如果您认为可能会引发异常,可以尝试使用 finally 重新附加事件。)

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    
        if ((e.AddedItems == null || e.AddedItems.Count == 0)) return;
        AssociatedObject.SelectionChanged -= OnSelectionChanged;
        SelectedValue = AssociatedObject.SelectedValue;
        AssociatedObject.SelectionChanged += OnSelectionChanged;
    }
    

    【讨论】:

    • 感谢您的回复,看来这与我尝试过的大多数事情都有相同的问题。它会询问两次以确认您是否要继续,它还会触发属性更改并在询问是否应该继续之前清除所有更改。
    猜你喜欢
    • 2017-01-22
    • 2019-03-24
    • 1970-01-01
    • 2021-09-01
    • 2023-03-28
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多