控件属性取决于其他控件';属性?(听众?)

本文关键字:控件 属性 听众 取决于 其他 | 更新日期: 2023-09-27 18:19:37

我已经习惯于通过创建一个检查方法并在每个处理程序中调用它来实现事件处理程序来设置特定控件的属性,比如:

private void checkProperties()
{
    myButton.IsEnabled = !String.IsNullOrWhiteSpace(myTextBox.Text) && myComboBox.SelectedIndex > -1;
}
private void myTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    checkProperties();
}
private void myComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    checkProperties();
}

<Window x:Class="MyProgram.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <TextBox Height="23" HorizontalAlignment="Left" Name="myTextBox" VerticalAlignment="Top" Width="120" TextChanged="myTextBox_TextChanged" />
        <ComboBox Height="23" HorizontalAlignment="Left" Margin="0,38,0,0" Name="myComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="myComboBox_SelectionChanged" />
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="45,84,0,0" Name="myButton" VerticalAlignment="Top" Width="75" IsEnabled="False" />
    </Grid>
</Window>

但是,当你有一个依赖于10个或更多其他控件属性的属性时,这会变得非常沉重和多余(想想向导窗口及其"下一步"按钮,只有当每个控件都有效时,它才应该启用)。

是否有方法修改属性以根据其他控件的属性自动更改

我读过一些关于依赖属性的文章,但我不确定我是否可以修改myButton的"IsEnabled"属性以满足我的期望。

控件属性取决于其他控件';属性?(听众?)

您不必处理事件。您应该使用元素绑定,它会自动绑定到目标属性值。但是,有问题的两个属性都应该是Dependency属性。这对你来说应该有效。

请参见此示例:http://msdn.microsoft.com/en-us/library/system.windows.data.binding.elementname(v=vs.110).aspx

考虑使用MVVM而不是代码隐藏。启用按钮是可测试的命令逻辑,可以通过ICommand.CanExecute委托在视图模型中非常简单地进行处理。不需要绑定,因为当UI更改时,WPF会自动调用CanExecute()。

class MyViewModel : INotifyPropertyChanged
{
    public ICommand SomeCommand { get; private set; }
    public string Text          { get; set; } //INPC omited for brevity
    public int    SelectedIndex { get; set; } //INPC omited for brevity
    public MyViewModel()
    {
        SomeCommand = new RelayCommand(DoSomeCommand, CanDoSomeCommand);
    }
    private void DoSomeCommand()
    {
        //Blah
    }
    private bool CanDoSomeCommand()
    {
        return !String.IsNullOrWhiteSpace(this.Text) && this.SelectedIndex > -1;
    }
}

WPF多绑定可能是您在类似情况下所需要的-多绑定WPF。

<Grid>
    ...
    <Grid.Resources>
        <somenamespace:ValidatorConverter x:Key="ValidatorConverterResource">
    </Grid.Resources>
        <TextBox Name="myTextBox"  ... />
        <ComboBox Name="myComboBox" ... />
        <Button Name="myButton" ...>
             <Button.IsEnabled>
                  <MultiBinding Converter="{StaticResource ValidatorConverterResource}"
                          ConverterParameter="Left">
                <Binding Path="Text"
                         ElementName="myTextBox" />
                <Binding Path="SelectedIndex"
                         ElementName="{myComboBoxSelf}" />
            </MultiBinding>
             </Button.IsEnabled>
        </Button>
</Grid>

但它实际上并不能缓解问题(它只是将它从代码隐藏转移到转换器):

public class ValidatorConverter: IConverter
{
     public object Converter( ...) //...
     public object ConverterBack( ...) //...
}

关于验证目标

可能有一些简单的方法可以做到这一点,但我不知道,所以至少要将问题整合到它所属的位置,最简单的方法是使用绑定和MVVM设计模式。

在模型(viewmodel)中创建一些IsValid属性(并直接或更好地通过命令将其绑定到Next IsEnabled),该属性将根据绑定属性的当前值进行更新。

public class WizardViewModel : INotifyPropertyChanged
{
     // OnPropertyChanged(String) and PropertyChanged event
     public String Text
     {
         get //..
         set
         {
              this._Text = value;
              Validate();
              this.OnPropertyChanged("SelectedItem")
         }
     }

     public Object SelectedItem
     {
         get //..
         set
         {
              this._SelectedItem = value;
              Validate();
              this.OnPropertyChanged("SelectedItem")
         }
     }
     public bool IsValid { // ...}
     private void Validate()
     {
         if (String.IsNullOrEmpty(this._Text))
             this.IsValid = false;
         // ....
      }
}

在xaml中:

<somenamespace:WizardViewModel x:Key="WizardViewModelInstance">
// ....
<Grid.DataContext="{StaticResource WizardViewModelInstance}">
// ....
<TextBox ... Text="{Binding Text}"/>
<ComboBox ... SelectedItem="{Binding SelectedItem}"/>
<Button  ... IsEnabled="{Binding IsEnabled}"/>

这样的解决方案将使您的逻辑与视图解耦,并将与此类验证相关的所有内容放在一个位置。

此外:

如果你想了解WPF验证,你可能想阅读http://msdn.microsoft.com/en-us/library/ms753962(v=vs.110).aspx

如果您想了解WPF命令,请阅读http://msdn.microsoft.com/en-us/magazine/dn237302.aspx