将按钮IsEnabled属性绑定到DataTemplate项状态和一个附加条件

时间:2015-04-07 16:43:22

标签: c# wpf

我有一个带有可编辑参数集合的对象,它被绑定为ItemsSourceItemsControl,以及一个检查所有参数值是否正常的属性。此属性绑定到按钮的IsEnabled

我还想在任何文本框有验证错误时验证按钮(Validation.HasError == true)。

提前致谢。

XAML:

<Window x:Class="MyWPFTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <ItemsControl ItemsSource="{Binding Path=MyObject.Parameters}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Path=Name}"></TextBlock>
                    <TextBox Text="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button IsEnabled="{Binding Path=MyObject.IsParametersOkay}">OK</Button>
</StackPanel>
</Window>

代码:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;

namespace MyWPFTest
{
public partial class MainWindow : Window
{
    ObjectWithParameters _MyObject = new ObjectWithParameters();
    public ObjectWithParameters MyObject { get { return _MyObject; } }
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

public class ObjectWithParameters : INotifyPropertyChanged
{
    ObservableCollection<Parameter> _Parameters = new ObservableCollection<Parameter>();
    public ObservableCollection<Parameter> Parameters { get { return _Parameters; } }
    public event PropertyChangedEventHandler PropertyChanged;
    public ObjectWithParameters()
    {
        var p1 = new Parameter("Parameter 1", 0); p1.PropertyChanged += ParameterChanged; Parameters.Add(p1);
        var p2 = new Parameter("Parameter 2", 0); p2.PropertyChanged += ParameterChanged; Parameters.Add(p2);
    }
    void ParameterChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsParametersOkay"));
    }
    public bool IsParametersOkay
    {
        get { return Parameters.FirstOrDefault(p => p.Value < 0) == null; }
    }
}

public class Parameter : INotifyPropertyChanged
{
    double val; 
    public double Value 
    { 
        get { return val; } 
        set { val = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value")); } 
    }
    public string Name { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    public Parameter(string name, double value) { Name = name; Value = value; }
}
}

2 个答案:

答案 0 :(得分:2)

结帐MultiTriggers

<Style.Triggers>
  <Trigger Property="IsEnabled" Value="false">
    <Setter Property="Background" Value="#EEEEEE" />
  </Trigger>

  <MultiTrigger>
    <MultiTrigger.Conditions>
      <Condition Property="HasItems" Value="false" />
      <Condition Property="Width" Value="Auto" />
    </MultiTrigger.Conditions>
    <Setter Property="MinWidth" Value="120"/>
  </MultiTrigger>

  <MultiTrigger>
    <MultiTrigger.Conditions>
      <Condition Property="HasItems" Value="false" />
      <Condition Property="Height" Value="Auto" />
    </MultiTrigger.Conditions>
    <Setter Property="MinHeight" Value="95"/>
  </MultiTrigger>
</Style.Triggers>

答案 1 :(得分:0)

这是我解决问题的方法。可能它不是一个非常优雅的解决方案,但它确实有效。

我向MainWindow类添加了一个新属性IsFormOkay,它检查控件和参数的有效性。然后我将Button.IsEnabled绑定到此属性并为TextBox添加了TextChanged事件以通知IsFormOkay。

以下是添加到MainWindow的代码:

    public event PropertyChangedEventHandler PropertyChanged;

    public bool IsFormOkay { get { return IsValid(Items) && MyObject.IsParametersOkay; } }

    public bool IsValid(DependencyObject obj)
    {
        if (Validation.GetHasError(obj)) return false;
        for (int i = 0, n = VisualTreeHelper.GetChildrenCount(obj); i < n; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (!IsValid(child)) return false;
        }
        return true;
    }

    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsFormOkay"));
    }

对XAML的更改:

<StackPanel>
    <ItemsControl x:Name="Items" ItemsSource="{Binding Path=MyObject.Parameters}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Path=Name}" />
                    <TextBox TextChanged="TextBox_TextChanged" Text="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged}" />
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button IsEnabled="{Binding Path=IsFormOkay}" Content="OK" />
</StackPanel>