【问题标题】:Bind Button IsEnabled property to DataTemplate items state and one additional condition将 Button IsEnabled 属性绑定到 DataTemplate 项状态和一个附加条件
【发布时间】:2015-04-07 16:43:21
【问题描述】:

我有一个带有可编辑参数集合的对象,该集合作为ItemsSource 绑定到ItemsControl,以及一个检查所有参数值是否正常的属性。此属性绑定到按钮的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; }
}
}

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    查看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>
    

    【讨论】:

    • 我应该如何编写条件来检查 TextBox 验证错误?
    【解决方案2】:

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

    我向 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>
    

    【讨论】:

      猜你喜欢
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多