ComboBox SelectedValue不会从绑定更改为依赖属性

时间:2014-03-10 12:35:11

标签: wpf custom-controls dependency-properties

我有自定义控件:

我不想详细说明,为了简单起见,我有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()zeros _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)问题,条件未达到,再次使用有效值设置值。

2.5)转到(1.4)

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

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

ComboBox in template , snooped

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

在这种情况下,任何想法都是为什么ComboBox不会通过Binding更新它的值?

3 个答案:

答案 0 :(得分:0)

我不知道我是否确实理解了这个问题,但你应该拥有的是对Combobox中SelectedItem的绑定。

当该值发生变化时,您应该使用INotifyPropertyChanged引发PropertyChanged事件。

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

你能用它吗?

此致

答案 1 :(得分:0)

O'k所以问题似乎是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

虽然这确实补丁并解决了这个问题,但后来我以更简单的方式重新编写了整个控件, 我所做的其中一件事是删除放置在Combobox的SelectedItem上的ValidationRule。

这样做时,我的DependencyProperty和Combox的SelectedItem之间的绑定正常更新。 仅供参考,我根据自己的经验将WPF验证系统的使用全部删除,但效果不佳 (我当然通常使用其他词来描述WPF验证,但不是在这里:))。

答案 2 :(得分:-1)

我没有完全按照这个过程进行操作,但我认为如果您的代码遵循快乐路径,则永远不会设置Value1。看起来在Value1设置了“未更正”值之后,您设置了InternalValue,然后像这样设置SelectedValue

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

之后OnSelectedValueChanged只重置标志并存在:

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

你似乎永远不会纠正Value1

但我可能会离开这里。