构建复杂条件绑定的最佳方法

时间:2017-06-22 14:31:13

标签: c# wpf binding

考虑一下我必须根据两个属性设置样式:

<Label Style={Binding IsEnabled, Convert={x:Static IsEnabledToStyleConverter}} />

<Label Style={Binding IsRequired, Convert={x:Static IsEnabledToStyleConverter}} />

确定与IsEnabledIsRequired绑定的用户是其他属性 - UseRequried。如何在UseRequired上选择这两个绑定盆地?

我试过方法:

  1. 另一个值转换器
  2. 我已创建自己的价值转换器:

    public class ControlToLableStleConverter: IValueConverter
    {
         public object Convert(object value..)
         {
              var myCtrl = (MyControl) value;
              if (myCtrl.UseRequired)
                 //return style based on IsRequired property
              else
                 //return style based on IsEnabled property
         }
    }
    

    但问题是样式在IsEnabledIsRequired更改时没有变化。非常明显,所以这个解决方案已经解决了。

    1. DataTrigger
    2. 我还创建了DataTriggers:

      <Label>
      <Label.Triggers>
          <DataTrigger Binding="{Binding UseRequired}" Value="True">
             <Setters>
                 <Setter Property="Style" Value="{Binding IsRequired ....">
             </Setters>
          </DataTrigger>
          <DataTrigger Binding="{Binding UseRequired}" Value="False">
             <Setters>
                 <Setter Property="Style" Value="{Binding IsEnabled ....">
             </Setters>
          </DataTrigger>
      </Label.Triggers>
      </Label>
      

      Label.Triggers只能包含EventTrigger元素。我还能做什么?

3 个答案:

答案 0 :(得分:3)

在这种情况下,您可以使用MultiBinding,但它可能非常详细:

<Label>
    <Label.Style>
        <MultiBinding Converter="{StaticResource yourConverter}">
            <Binding Path="IsEnabled" />
            <Binding Path="IsRequired" />
        </MultiBinding>
    </Label.Style>
</Label>

然后转换器:

public class StyleConverter : IMultiValueConverter {
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
        // take some caution here, because values can be null or DependencyProperty.UnsetValue in certain cases
        var enabled = (bool) values[0];
        var required = (bool) values[1];
        // choose style
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
        throw new NotImplementedException();
    }
}

答案 1 :(得分:1)

在样式中设置触发器。

<Style TargetType="{x:Type MyControl}">
 <Style.Triggers>
  <DataTrigger Binding="{Binding UseRequired}" Value="True">
       <Setters>
           <!-- Set properties here, not the Style -->
       </Setters>
    </DataTrigger>
    <DataTrigger Binding="{Binding UseRequired}" Value="False">
       <Setters>
          <!-- Set properties here, not the Style -->           
       </Setters>
    </DataTrigger>
 </Style.Triggers>
</Style>

如果您无法更改属性,那么最佳选择是使用StyleSelector (MSDN)

答案 2 :(得分:0)

将此类逻辑放在后面的代码中并触发UseRequiered(或其他地方)的更改并触发所有属性更改,例如

public bool UseRequiered 
{ 
    get { return _UseRequried; }
    set { _UseRequried = value; DetermineStyle(); }// PropertyChanged in DetermineStyle()

}

public bool IsRequiered
{
    get { return _IsRequiered; }
    set { _IsRequiered = value; DetermineStyle();} // PropertyChanged in DetermineStyle()
}

public bool IsEnabled 
{ 
   get { return _IsEnabled; }
   set { _IsEnabled = value; DetermineStyle(); } // Prop change in DetermineStyle
}

private void DetermineStyle()
{
     _UseRequiered = { Whatever logic is deemed };
     _IsRequired  =  { Whatever logic is deemed };
     _IsEnabled   =  { Whatever logic is deemed };

     OnPropertyChanged("IsRequired");
     OnPropertyChanged("IsEnabled");
     OnPropertyChanged("UseRequiered"); 
}