【问题标题】:PropertyChangedCallback is not getting fired during callback when a value in ViewModel is changed当 ViewModel 中的值发生更改时,PropertyChangedCallback 在回调期间不会被触发
【发布时间】:2017-01-25 13:58:30
【问题描述】:

我有一个使用 SearchBox 用户控件的视图,SearchBox 有两个单选按钮来选择搜索模式 - 即时和延迟。我已经将 searchmodes 绑定到 SearchMode 属性,并且我还为 Search Mode 创建了一个自定义依赖属性。

查看

<controls:SearchBox Grid.Row="0"
              HorizontalAlignment="Right"
              Margin="2" Width="200"                           
              SearchMode="{Binding DataContext.SearchMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }" />

ViewModel.cs

private Mode mSearchMode;
            public Mode SearchMode
            {
                get
                {
                    return mSearchMode;
                }
                set
                {
                    mSearchMode = value;
                    NotifyOfPropertyChange();
                }
            }

      // Called when application is restarted.
      private void ActivateLastSelectedSearchMode(Mode lastselectedMode)
            {    
               // Sets the last selected mode to the search mode      
                SearchMode =  lastselectedMode;
            }

         public enum Mode
            {
                Instant,
                Delayed,
            }

SearchBox.xaml

<UserControl x:Class = "abc.SearchBox"
                 DataContext="{Binding RelativeSource={RelativeSource Self}}" >

   <UserControl.Resources>
            <converters:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
    </UserControl.Resources>

    <StackPanel Orientation="Vertical">
     <RadioButton Content="{lex:Loc SearchBox:SearchModelInstatOption}"
                 IsChecked="{Binding Path=SearchMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Mode.Instant}}" />
     <RadioButton Content="{lex:Loc SearchBox:SearchModeDelayedOption}"
                 IsChecked="{Binding Path=SearchMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Mode.Delayed}}" />
    </StackPanel>
    </UserControl>

SearchBox.xaml.cs

public partial class SearchBox : UserControl
    {
      public static DependencyProperty SearchModeProperty =
                    DependencyProperty.Register(
                        "SearchMode",
                        typeof(Mode),
                        typeof(SearchBox),
                        new FrameworkPropertyMetadata(default(Mode), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsSearchModeChanged));

    static void OnIsSearchModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {            
                var searchBox = obj as SearchBox;
                searchBox.SearchMode = (Mode)e.NewValue;                 

            }

              public Mode SearchMode
            {
                get { return (Mode)GetValue(SearchModeProperty); }
                set { SetValue(SearchModeProperty, value); }
            }

    }

我希望每次在回调期间设置 SearchMode 时触发 OnIsSearchModeChanged(),即在 ViewModel.cs 中调用 ActivateLastSelectedSearchMode()。我完全一无所知..我在哪里失踪,我无法取得成功。

【问题讨论】:

    标签: xaml mvvm data-binding dependency-properties caliburn.micro


    【解决方案1】:
    //snip
    
        private Mode mSearchMode;
                    public Mode SearchMode
                    {
                        get
                        {
                            return mSearchMode;
                        }
                        set
                        {
                            mSearchMode = value;
                            NotifyOfPropertyChange(()=>SearchMode); //Change
                     }
                    }
    

    反映的变化有什么不同吗?其他选项是为您的用户控件创建自定义约定

    【讨论】:

      【解决方案2】:

      您应该在视图模型中创建一个事件并从您的代码中订阅它。

      在您的视图模型中:

       public event SearchModeAction SearchModeChanged;
       public delegate void SearchModeAction(object sender, EventArgs e);
       public void SearchModeHasChanged()
              {
                  SearchModeAction Handler = SearchModeChanged;
                  if (Handler != null)
                  {
                      Handler(this, null);
                  }
              }
      private void ActivateLastSelectedSearchMode(Mode lastselectedMode)
                  {    
                     // Sets the last selected mode to the search mode      
                      SearchMode =  lastselectedMode;
                      SearchModeHasChanged()
                  }
      

      在你的代码后面:

       private void Window_Loaded(object sender, RoutedEventArgs e)
              {
                 ((YourViewModelClass)DataContext).SearchModeChanged += OnIsSearchModeChanged;
              }
      
      private void OnIsSearchModeChanged(object sender, EventArgs e)
              {
                   var searchBox = obj as SearchBox;
                   searchBox.SearchMode = (Mode)e.NewValue;         
              }
      

      这样,每次您到达 View Model 中的 ActivateLastSelectedSearchMode 方法时,您都会在 View 中调用 OnIsSearchModeChanged 方法。

      【讨论】:

        【解决方案3】:

        啊..原因是 EnumToBooleanConverter。

        虽然“参数”和“值”的值相同,但它们的对象类型之间存在差异,因为它们都引用了不同的命名空间。所以我创建了一个名为“Mode”的公共枚举,并确保“Instant”和“Delayed”引用相同的命名空间。

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
                {
                    if (value == null)
                    {
                        return false;
                    }
        
                    return value.Equals(parameter); // This always returned false despite the values being the same
                }
        

        【讨论】:

          猜你喜欢
          • 2020-06-10
          • 1970-01-01
          • 1970-01-01
          • 2015-05-10
          • 2017-11-28
          • 1970-01-01
          • 1970-01-01
          • 2016-06-05
          • 1970-01-01
          相关资源
          最近更新 更多