WPF: Reapply DataTemplateSelector when a certain value changes

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

So here is the XAML that I have:



        
5条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-11 00:47

    I do it with a binding proxy.

    It works like a normal binding proxy (but with 2 Props - copies data from DataIn to DataOut), but sets the DataOut to NULL and back to the DataIn value whenever the Trigger value changes:

    public class BindingProxyForTemplateSelector : Freezable
    {
        #region Overrides of Freezable
    
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxyForTemplateSelector();
        }
    
        #endregion
    
        public object DataIn
        {
            get { return (object)GetValue(DataInProperty); }
            set { SetValue(DataInProperty, value); }
        }
    
        public object DataOut
        {
            get { return (object) GetValue(DataOutProperty); }
            set { SetValue(DataOutProperty, value); }
        }
    
        public object Trigger
        {
            get { return (object) GetValue(TriggerProperty); }
            set { SetValue(TriggerProperty, value); }
        }
    
    
        public static readonly DependencyProperty TriggerProperty = DependencyProperty.Register(nameof(Trigger), typeof(object), typeof(BindingProxyForTemplateSelector), new PropertyMetadata(default(object), OnTriggerValueChanged));
    
        public static readonly DependencyProperty DataInProperty = DependencyProperty.Register(nameof(DataIn), typeof(object), typeof(BindingProxyForTemplateSelector), new UIPropertyMetadata(null, OnDataChanged));
    
        public static readonly DependencyProperty DataOutProperty = DependencyProperty.Register(nameof(DataOut), typeof(object), typeof(BindingProxyForTemplateSelector), new PropertyMetadata(default(object)));
    
    
    
        private static void OnTriggerValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // this does the whole trick
    
            var sender = d as BindingProxyForTemplateSelector;
            if (sender == null)
                return;
    
            sender.DataOut = null; // set to null and then back triggers the TemplateSelector to search for a new template
            sender.DataOut = sender.DataIn;
        }
    
    
    
        private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var sender = d as BindingProxyForTemplateSelector;
            if (sender == null)
                return;
    
            sender.DataOut = e.NewValue;
        }
    
    }
    

    Use it like this:

    
        
            
        
        
    
    

    So you don't bind to your DataContext directly, but to the BindingProxy's DataOut, which mirrors the original DataContext, but with a small difference: When the trigger changes (in this example a bool value inside the 'Item'), the TemplateSelector gets retriggered.

    You don't have to change your TemplateSelector for this.

    It is also possible to add more Triggers, just add a Trigger2.

提交回复
热议问题