控制属性取决于其他控件'属性? (监听器?)

时间:2014-08-27 09:17:15

标签: c# wpf xaml listener

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

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个或更多其他控件属性的属性时,这会变得非常沉重和冗余(只需考虑一个向导窗口及其“下一步”按钮,只有在每个控件都有效时才应该启用)

有没有办法根据其他控件的属性修改属性以自动更改?

我已经阅读了Dependency Properties一点,但我不确定,我可以修改myButton的“IsEnabled”属性以满足我的期望。

3 个答案:

答案 0 :(得分:0)

您不必处理事件。您应该使用元素绑定,它自动绑定到目标属性值。但是,这两个属性都应该是Dependancy属性。它应该适用于你的情况。

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

答案 1 :(得分:0)

WPF Multibinding可能就是您在类似情况下所需要的 - Multibinding 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>

但它实际上并没有解决问题(它只是将其从代码隐藏to converters移开):

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

关于验证目标

可能有一些简单的方法,但我不知道,所以至少将问题合并到它所属的最简单方法是使用bindings和{{3} }。

MVVM design pattern中创建一些IsValid属性(并将其直接绑定到Next IsEnabled,甚至更好 - model(viewmodel)),这将根据绑定属性的当前值进行更新

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验证,可能需要阅读through the command

如果您想了解WPF命令,请阅读http://msdn.microsoft.com/en-us/library/ms753962(v=vs.110).aspx

答案 2 :(得分:0)

考虑使用MVVM而不是代码。启用按钮是可测试的命令逻辑,可以通过ICommand.CanExecute委托在视图模型中非常简单地处理。由于WPF在UI更改时自动调用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;
    }
}