C# 如何避免转换器与WPF代码隐藏中的多重绑定冲突
我在代码隐藏中动态地创建WPF元素,并且对于C# 如何避免转换器与WPF代码隐藏中的多重绑定冲突,c#,wpf,dynamic-binding,C#,Wpf,Dynamic Binding,我在代码隐藏中动态地创建WPF元素,并且对于网格中的每一行我正在构建它,它由一个复选框和一个动态的文本框组成。所需的交互作用如下: 如果一行中的所有文本框的值均为0,请设置复选框 将属性选中为true并禁用它 如果其中一个文本框从0更改,请启用 复选框并将IsChecked设置为false 如果用户单击复选框,则设置所有相关的文本框 到0并禁用复选框 我能够使用以下代码完成最后一部分的第一部分: Binding setScoreToZeroIfIsNormalChecked = new Bi
网格中的每一行
我正在构建它,它由一个复选框和一个动态的文本框组成。所需的交互作用如下:
- 如果一行中的所有
文本框
的值均为0
,请设置复选框
将
属性选中为true
并禁用它李>
- 如果其中一个
文本框从0
更改,请启用
复选框
并将IsChecked
设置为false
- 如果用户单击
复选框
,则设置所有相关的文本框
到0
并禁用复选框
我能够使用以下代码完成最后一部分的第一部分:
Binding setScoreToZeroIfIsNormalChecked = new Binding("IsChecked");
setScoreToZeroIfIsNormalChecked.Source = this.NormalCheckBoxControl;
setScoreToZeroIfIsNormalChecked.Converter = m_NormalCheckBoxJointScoresConverter;
tempJointScoreControl.JointScoreContainer.SetBinding(ContainerBase.SingleAnswerProperty, setScoreToZeroIfIsNormalChecked);
和转换器:
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool && targetType == typeof(Answer))
{
if ((bool)value)
{
Answer answer = new Answer();
answer.Value = "0";
answer.DisplayValue = "0";
return answer;
}
else
return null;
}
else
{
return null;
}
}
然而,在尝试创建另一个转换器以实现其他功能时,我遇到了转换器相互重叠的问题,因为所有功能都基于复选框.IsChecked
属性
使用一个或两个多绑定转换器是否可以实现上述所有功能?我真的不想为了做到这一点而创建一大堆事件并维护它们。如果您使用MVVM,这个问题可以很容易地解决
您将拥有一个表示网格中的行的ViewModel。每个文本框有一个属性,复选框有一个属性
此外,对于包含网格的视图,您将有一个ViewModel,该ViewModel将公开行ViewModels的集合
您所在行的ViewModel:
public class AnswersViewModel : ViewModelBase // From MvvmLight
{
public bool IsAnswered
{
get { return _isAnswered; }
set
{
if(value == _isAnswered)
return;
_isAnswered = value;
if(_isAnswered)
{
Answer1 = "0";
Answer2 = "0";
}
RaisePropertyChanged("IsAnswered");
}
}
public string Answer1
{
get { return _answer1; }
set
{
if(value == _answer1)
return;
_answer1 = value;
RaisePropertyChanged("Answer1");
if(_answer1 == "0" && _answer2 == "0")
{
_isAnswered = true;
RaisePropertyChanged("IsAnswered");
}
}
}
// The implementation of Answer2 is similar to Answer1
}
视图的ViewModel:
public class FooViewModel : ViewModelBase
{
public ObservableCollection<AnswersViewModel> Answers
{
get { return _answers; }
}
}
公共类FooViewModel:ViewModelBase
{
公开收集答案
{
获取{return\u answers;}
}
}
您的视图将包含带有ItemsSource=“{Binding Answers}”
的网格和绑定到AnswersViewModel
属性的项的控制模板
禁用我将通过样式中的触发器处理的复选框。这相对容易。应围绕复选框IsChecked属性解决所有问题。
原因很简单,它是一个双向属性。所以,您可以修改它,或者复选框可以修改它
因此,您可以使用多重绑定,例如:
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = multiBindingConverter;
multiBinding.Bindings.Add(new Binding("Text") { Source = txtbox1});
multiBinding.Bindings.Add(new Binding("Text") { Source = txtbox2});
multiBinding.NotifyOnSourceUpdated = true;//this is important.
checkBox.SetBinding(CheckBox.IsCheckedProperty, multiBinding);
在multiBindingConverter中,您将使用object[]value作为第一个参数,如果您应该返回true/false,则需要将其转换为IList并对其进行迭代(&D)进行计算。(IsChecked=true或false)
现在,将复选框绑定到复选框IsChecked属性,并使用BooleanInvertorConverter。(如果选中复选框,则应禁用该复选框,反之亦然)
最后一步是使文本框侦听CheckBox的实际IsChecked属性。
如果这是真的,它们都应该显示值0,否则它们可以显示它们想要的
因此,创建一个新的多重绑定
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = textboxMultiBindingConverter;
multiBinding.Bindings.Add(new Binding("IsChecked") { Source = checkbox1});
multiBinding.Bindings.Add(new Binding("Text") { Source = textbox1});
multiBinding.NotifyOnSourceUpdated = true;//this is important.
textbox1.SetBinding(TextBox.Text, multiBinding);
textboxMultiBindingConverter中的思想是,如果值[0]==FALSE,则返回文本(值[1]),如果值[0]==TRUE,则返回“0” 在代码中创建控件是否有特定的原因?是否使用MVVM设计模式?这将是在您的数据项中完成的非常简单的逻辑,而不是使用转换器使您的UI实现您想要的。如果您不使用MVVM,最好只处理复选框。单击和文本框。TextChanged
事件并调整代码中其他对象的值。您应该只需要两个事件,一个用于所有复选框
,一个用于所有文本框
。两者都只能影响与更改的项共享相同的网格。行
。@DanielHilgarth所有内容都是动态创建的,因此UserControls的所有xaml仅代表单个实例。您有MVVM的示例吗?我以前在几个简单的应用程序中使用过它,但如果说我完全理解发生了什么,那我就是在撒谎;我从来没能完全把握住我的前进方向,结果是经过了大量的尝试,摸索了很久error@user564636如果你感兴趣的话,我有一个好主意。起初我也很难理解MVVM设计模式,因为当时所有现有的材料对我来说都太高了,所以一旦我理解了它,我就为我的博客写了一个非常基本的MVVM示例,试图帮助其他人也更容易理解它。如果你与WPF合作,这确实是一个很棒的设计模式:)@Rachel和Daniel,感谢你们两位为我提供了一些关于MVVM方法的见解!这肯定是我将学习的东西,并期待在未来的应用程序中实现。不幸的是,由于时间限制,将已经开发的东西转换成MVVM范例是不可行的。谢谢,这非常有帮助!我能够实现很多,但是在调用ConvertBack方法时(例如,当我单击复选框时)会出现错误。我从未见过在多绑定转换器中实现ConvertBack()方法,我需要将绑定模式设置为单向吗?谢谢;经过一些修改,我能够用绑定/转换器完成所有工作,除了在切换复选框时将行中所有关联的文本框设置为“0”;事实证明,动态创建控件的方式非常混乱/复杂,因此我所要做的就是向CheckBox.ischeck添加一个侦听器,并使用一个简单的foreach循环进行检查。