如何避免转换器与WPF代码multibinding冲突背后

问题描述 投票:6回答:2

我在代码中动态创建WPF元素的背后,并为每个在我建立它Grid行由一个CheckBoxTextBoxes的动态数量。所需要的相互作用如下:

  • 如果行中的所有TextBoxes0值,设置CheckBox IsChecked属性true并禁用它。
  • 如果TextBoxes的一个,然后从0改变,使CheckBox并设置IsCheckedfalse
  • 如果用户点击CheckBox,将所有相关TextBoxes0和禁用CheckBox

我能做到使用此代码的最后一个的第一部分:

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;
    }
}

然而,在试图创建另一个转换器来实现其他功能,我也陷入了转换踩着彼此的问题,因为所有的功能是根据各地的CheckBox.IsChecked财产。

反正是有完成上述所有使用一个或两个multibinding转换器?我真的希望避免创造了一大堆事件,并维持他们为了做到这一点。

c# wpf dynamic-binding
2个回答
10
投票

这是相对容易的。一切都应该围绕解决复选框财产器isChecked。理由很简单,这是一个双向的财产。因此,无论你可以修改它,或复选框可以修改它。

所以,你做什么,你使用MultiBinding,因为这样的:

    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,你将有对象[]值作为第一个参数,它需要转换成IList中,并遍历它&&做你的计算,如果你要么返回真/假。(=器isChecked true或false)

现在绑定复选框的IsEnabled到复选框财产器isChecked,并使用BooleanInverterConverter。 (如果复选框被选中,就应该被禁止,反之亦然)

最后一步是使文本框听CheckBox的实际财产器isChecked。如果这是真的,他们都应该显示为0值,否则他们可以展示他们想要的东西。

所以,做一个新的MultiBinding。

    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的想法是要么返回文本(值[1])如果值[0] == FALSE或 “0”,如果值[0] == TRUE。


1
投票

这个问题可以很容易解决,如果你会使用MVVM。

你将不得不表示在网格行中的视图模型。这将有复选框每一个文本框财产和一个。

此外,您必须包含网格和这个视图模型将暴露行的ViewModels的集合视图一个视图模型。

该视图模型为您排:

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
}

该视图模型的视图:

public class FooViewModel : ViewModelBase
{
    public ObservableCollection<AnswersViewModel> Answers
    {
        get { return _answers; }
    }
}

您的视图将包含与ItemsSource="{Binding Answers}"网格和控件模板的结合到AnswersViewModel的性质的项目。

禁用复选框我将通过在样式扳机手柄。

© www.soinside.com 2019 - 2024. All rights reserved.