【问题标题】:ComboBox SelectedValue not changing from binding to Dependency PropertyComboBox SelectedValue 不会从绑定更改为依赖属性
【发布时间】:2014-04-13 13:30:41
【问题描述】:

我有一个自定义控件:

我不想详细说明,所以为了简单起见,我有 3 个依赖属性:

MyCustomControl (CS):

public class MyCustomControl : Control
{
    DP Value1
    DP InternalValue
    DP SelectedValue 


   OnValue1Changed()
   {
       InternalValue = CalculateBasedOn1();
   }

   static bool _isSetInternally;  
   OnInternalValueChanged()
   {
       if(Condition())
       {
           _isSetInternally = true;
           SelectedValue = e.NewValue;
       }
       else
       {
           Value1 = FixValue1();                        
       } 
   }

   OnSelectedValueChanged()
   {
       if(_isSetInternally)
       {
          _isSetInternally = false;
          return; 
       }

       Value1 = ExtractValue1FromInput(e.NewValue);
   }

   public List<string> Values
   {
       get{ return new List<string>() { "1","2",......,"200"};}
   }

 }

我的 ControlTemplate(再次简化):

    <ControlTemplate>
        <ComboBox x:Name="cb" 
           ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, Path=Values}"
           SelectedItem={Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
    </ControlTemplate>

问题: cb 显示的是最后选择的值,即使它已按如下所述进行修复。

流程:

1) 输入:

1.1) SelectedValue 绑定到我的 DataContext 中的一个属性,它接收一个值。

1.2) OnSelectedValueChanged() 设置 Value1。

1.3) Value1 通过绑定设置“cb”SelectedItem。

1.4) OnValue1Changed 设置 InternalValue。

1.5) OnInternalValueChanged() 标志 _isSetInternally = true 并更新 SelectedValue。

1.6) OnSelectedValueChanged() 将 _isSetInternally = false 归零并停止流动(返回)。

2) 输出:

2.1) cb 的 SelectedItem 发生了变化。

2.2) Value1 通过 Binding 设置。

2.3) OnValue1Changed() 设置 InternalValue。

2.4) 如果满足条件,则传播输出。

2.4.1) 转到 (1.4)

2.4.2) 问题,不满足条件,重新设置 Value1 为有效值。

2.5) 转到 (1.4)

2.4.2中的问题是ComboBox仍然显示在(2.1)中选择的无效值

用 snoop 观察我可以看到 SelectedItem 是正确的并且已更改,但 SelectedValue 和 SelectedIndex 仍然是在修复之前选择的。

*进一步尝试在强制回调上强制 Value1 ,它具有相同的效果。

知道为什么 ComboBox 在这种情况下不通过绑定更新它的值吗?

【问题讨论】:

  • 仅供参考,我还尝试了绑定到 SelectedValue 而不是 SelectedItem 并使用 OneWay 绑定使用 SelectedValue 绑定到它们。

标签: wpf custom-controls dependency-properties


【解决方案1】:

我不知道我是否很好地理解了这个问题,但你应该有一个绑定到 Combobox 中的 SelectedItem。

当该值更改时,您应该使用 INotifyPropertyChanged 引发 PropertyChanged 事件。

在您的组合中,您将拥有 DisplayMemberPath 和 SelectedValuePath 属性。

你能用它吗?

问候,

【讨论】:

  • 你会给 SelectedValuePath 什么? ,我不需要在这里使用 INotifyPropertyChanged ,这是 2 个 DP 之间的绑定,他们提出了自己的通知。
  • stackoverflow.com/questions/3797034/… 类似这个例子吗?
  • 你是说我需要 SelectedValuePath 吗?请注意,我的 ItemsSource 只是一个 List 我如何将 SelectedValuePath 指定为实际项目。
【解决方案2】:

好吧,问题似乎是 ComboBox 中的一些同步问题 根据这篇文章:

http://ikriv.com/dev/wpf/ConfusedComboBox/index.shtml

特别感谢Uriel Jacobson

建议使用 Dispatcher.BeginInvoke(...) 对 ComboBox 进行异步更新

 OnInternalValueChanged()
 {
     if(Condition())
     {
         _isSetInternally = true;
         SelectedValue = e.NewValue;
     }
     else
     {
         Application.Current.Dispatcher.BeginInvoke(new System.Action(() =>
         {
             Value1 = FixValue1();
         }));                      
     } 
 }

编辑:19.7.2014

虽然这确实修补并修复了这个问题,但我后来以更简单的方式重新编写了整个控件, 我做的一件事是删除我放在绑定到组合框的 SelectedItem 上的 ValidationRule。

这样做时,我的 DependencyProperty 和 Combox 的 SelectedItem 之间的绑定正常更新。 仅供参考,根据我的经验,我一起删除了 WPF 验证系统的使用,它们只是不能很好地工作 (我当然通常用其他词来描述 WPF Validations ,但不是在这里 :))。

【讨论】:

    【解决方案3】:

    我并没有完全遵循这里的过程,但我认为如果您的代码遵循快乐路径,则永远不会设置 Value1。看起来Value1 设置为“未更正”值后,您设置InternalValue,然后像这样设置SelectedValue:

    if(Condition())
    {
        _isSetInternally = true;
        SelectedValue = e.NewValue;
    }
    

    然后OnSelectedValueChanged 只是重置标志并存在:

    if(_isSetInternally)
    {
       _isSetInternally = false;
       return; 
    }
    

    你似乎从来没有纠正过Value1。

    但我可能会离开这里。

    【讨论】:

    • OnInternalValueChanged 更正了 Value1 ,所有的依赖属性都设置为正确的值,这是 ComboBox 的 SelectedValue 不正确。
    • @eranotzap - 正如您发布的那样,OnInternalValueChanged 不会更改 Value1。如果条件满足,则只设置标志SelectedValue,然后退出。
    • else { Value1 = FixValue1(); }
    • @eranotzap - 你说问题出现在你的快乐路径中,当条件为真时 - 然后 else 永远不会运行。
    • 你说得对,我写的是 2.4.1 而不是 2.4.2 ,我没有修复它。
    猜你喜欢
    • 2011-04-17
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    相关资源
    最近更新 更多