我有自定义控件:
我不想详细说明,为了简单起见,我有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之前选择的那个。
*进一步尝试在强制回调中强制执行Value1,它具有相同的效果。
在这种情况下,任何想法都是为什么ComboBox不会通过Binding更新它的值?
答案 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
。
但我可能会离开这里。