WPF: Reapply DataTemplateSelector when a certain value changes

后端 未结 5 1885
Happy的楠姐
Happy的楠姐 2020-12-10 23:55

So here is the XAML that I have:



        
5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-11 00:39

    I wasn't really satisfied with the solutions I will post the way I've managed to get the selector check for changes:

    public class DynamicSelectorContentControl : ContentControl
    {
        // Using a DependencyProperty as the backing store for ListenToProperties.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ListenToPropertiesProperty =
            DependencyProperty.Register("ListenToProperties", typeof(string),
                typeof(DynamicSelectorContentControl),
                new FrameworkPropertyMetadata(string.Empty));
    
        public DynamicSelectorContentControl()
        {
            this.DataContextChanged += DynamicSelectorContentControl_DataContextChanged;
        }
    
        public string ListenToProperties
        {
            get { return (string)GetValue(ListenToPropertiesProperty); }
            set { SetValue(ListenToPropertiesProperty, value); }
        }
        private void CheckForProperty(object sender, PropertyChangedEventArgs e)
        {
            if (ListenToProperties.Contains(e.PropertyName))
            {
                ClearSelector();
            }
        }
    
        private void ClearSelector()
        {
            var oldSelector = this.ContentTemplateSelector;
            if (oldSelector != null)
            {
                this.ContentTemplateSelector = null;
                this.ContentTemplateSelector = oldSelector;
            }
        }
    
        private void DynamicSelectorContentControl_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var listOfProperties = ListenToProperties.Split(',').Select(s => s.Trim());
    
            var oldObservable = e.OldValue as INotifyPropertyChanged;
    
            if (oldObservable != null && listOfProperties.Any())
            {
                PropertyChangedEventManager.RemoveHandler(oldObservable, CheckForProperty, string.Empty);
            }
    
            var newObservable = e.NewValue as INotifyPropertyChanged;
    
            if (newObservable != null && listOfProperties.Any())
            {
                PropertyChangedEventManager.AddHandler(newObservable, CheckForProperty, string.Empty);
            }
    
            if (e.OldValue != null)
            {
                ClearSelector();
            }
        }
    }
    

    Usage in XAML:

                                    
    

    This could be changed to have the dependency be a list, but a string was better for my case. It works well and has no memory leak. Besides, you can have you DataTemplates in an extra file which does not garbage your main xaml.

    Cheers, Marco

提交回复
热议问题