Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何避免转换器与WPF代码隐藏中的多重绑定冲突_C#_Wpf_Dynamic Binding - Fatal编程技术网

C# 如何避免转换器与WPF代码隐藏中的多重绑定冲突

C# 如何避免转换器与WPF代码隐藏中的多重绑定冲突,c#,wpf,dynamic-binding,C#,Wpf,Dynamic Binding,我在代码隐藏中动态地创建WPF元素,并且对于网格中的每一行我正在构建它,它由一个复选框和一个动态的文本框组成。所需的交互作用如下: 如果一行中的所有文本框的值均为0,请设置复选框 将属性选中为true并禁用它 如果其中一个文本框从0更改,请启用 复选框并将IsChecked设置为false 如果用户单击复选框,则设置所有相关的文本框 到0并禁用复选框 我能够使用以下代码完成最后一部分的第一部分: Binding setScoreToZeroIfIsNormalChecked = new Bi

我在代码隐藏中动态地创建WPF元素,并且对于
网格中的每一行
我正在构建它,它由一个
复选框和一个动态的
文本框组成。所需的交互作用如下:

  • 如果一行中的所有
    文本框
    的值均为
    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循环进行检查。