基于多个属性禁用按钮。我使用MultiDataTrigger和MultiBinding [英] Disabling button based on multiple properties. I'm using MultiDataTrigger and MultiBinding

查看:174
本文介绍了基于多个属性禁用按钮。我使用MultiDataTrigger和MultiBinding的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经放下了我能想出来的最简单的例子,来证明我的问题。我试图启用基于2个条件中的1个按钮
1)Textbox1是可见的,内容是有效的

2)Textbox2是可见的,内容是有效的



我似乎正在按照可见性启用按钮,但IsValid方面给我的悲伤。



对于按钮,我已经引入了MultiDataTrigger和MultiBinding与MultiBinding Converter方法来评估该按钮是否应该启用。当我在编辑框之间切换(通过单击一个单选按钮)时调用该方法(称为myConverter),但是当编辑框中的数据有效,无效或两者之间的转换时似乎不被调用。很可能,我没有正确处理Validation.HasError



我的具体问题:
1)处理这个问题的正确模式是什么?任何例子?我应该说我已经简化了这个问题。例如,验证可能不只是必须是八个字符,并且可能会涉及到多个编辑框(例如地址和zip或地址和状态,因此我认为我可能需要MultiBinding转换器的想法,但我对其他想法开放!
2)如何处理我的Converter方法中的Validation.HasError?我把它当作ReadOnlyCollection,这可能是完全错误的!
3)我认为我的很大一部分问题是由于处理错误信息的许多选择。鉴于我正在使用ValidationRules,我还应该从属性中抛出异常以返回编辑字段?他们会不会打电话?你可以推荐一篇文章来显示不同的验证方式吗?



我已经把所有的代码放在下面。如果有人可以快速看看我的方向,我会非常感激的。
-Dave
XAML代码

 < Window x:Class =StackOverFlowBindingExample.Window1
xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/xaml
xmlns:local =clr-namespace:StackOverFlowBindingExample
Title =Window1Height =AutoMinWidth =500SizeToContent =ManualWindowStartupLocation =CenterOwnerResizeMode =CanResizeWithGrip>
< Window.Resources>
< local:MyConverter x:Key =myConverter/>
< Style x:Key =textStyleTextBoxTargetType =TextBox>
< Setter Property =ForegroundValue =#333333/>
< Setter Property =VerticalAlignmentValue =Top/>
< Setter Property =MinHeightValue =2/>
< Setter Property =MinWidthValue =100/>
< Setter Property =MarginValue =4/>
< Setter Property =MaxLengthValue =23/>
< Setter Property =VerticalContentAlignmentValue =Center/>
< Setter Property =Horizo​​ntalAlignmentValue =Left/>


< Style.Triggers>
< Trigger Property =Validation.HasErrorValue =true>
< Setter Property =ToolTipValue ={Binding RelativeSource = {RelativeSource Self},
Path =(Validation.Errors)[0] .ErrorContent}/>
< / Trigger>
< /Style.Triggers>
< / Style>



< /Window.Resources>
< Grid>
< StackPanel Orientation =Vertical>
< StackPanel Orientation =Horizo​​ntal>
< StackPanel Orientation =Vertical>
< RadioButton Name =m_radio1Margin =4GroupName =IdInputTypeIsChecked =TrueChecked =IdInputType_Changed>使用Inputtype1< / RadioButton>
< RadioButton Name =m_radio2Margin =4GroupName =IdInputTypeIsChecked =FalseChecked =IdInputType_Changed>使用Inputtype2< / RadioButton>
< / StackPanel>
< DockPanel Name =Grp8Digit>
< Label MinHeight =25Margin =4VerticalAlignment =TopVerticalContentAlignment =CenterHorizo​​ntalAlignment =LeftMinWidth =100Width =113> Type 1 Id: /标签>
< TextBox Height =23Name =m_textBox8DigitIdMaxLength =8Width =120Style ={StaticResource textStyleTextBox}Validation.Error =TextBox_Error>
< TextBox.Text>
< Binding>
< Binding.ValidatesOnExceptions> true< /Binding.ValidatesOnExceptions>
< Binding.ValidatesOnDataErrors> true< /Binding.ValidatesOnDataErrors>
< Binding.UpdateSourceTrigger> PropertyChanged< /Binding.UpdateSourceTrigger>
< Binding.Path> EightDigitId< /Binding.Path>
< Binding.NotifyOnValidationError> true< /Binding.NotifyOnValidationError>
< Binding.ValidationRules>
< local:EightByteStringConvertRule />
< /Binding.ValidationRules>
< / Binding>
< /TextBox.Text>
< / TextBox>
< Label MinHeight =25Margin =4VerticalAlignment =TopVerticalContentAlignment =CenterHorizo​​ntalAlignment =LeftMinWidth =100>输入8位数id< / Label>
< / DockPanel>
< DockPanel Name =Grp5DigitVisibility =Collapsed>


< StackPanel Orientation =Horizo​​ntal>
< Label MinHeight =25Margin =4VerticalAlignment =TopVerticalContentAlignment =CenterHorizo​​ntalAlignment =LeftMinWidth =100Width =113> Type 2 id: /标签>

< TextBox Name =m_textBox5DigitIdStyle ={StaticResource textStyleTextBox}MinHeight =25Margin =4VerticalAlignment =TopMaxLength =23VerticalContentAlignment =CenterHorizo​​ntalAlignment =LeftMinWidth =100Width =100ToolTip =Enter Type 2 id>
< TextBox.Text>
< Binding>
< Binding.ValidatesOnExceptions> true< /Binding.ValidatesOnExceptions>
< Binding.Path> FiveDigitId< /Binding.Path>

< Binding.NotifyOnValidationError> true< /Binding.NotifyOnValidationError>
< Binding.ValidationRules>
< local:FiveByteStringConvertRule />
< /Binding.ValidationRules>
< / Binding>
< /TextBox.Text>
< / TextBox>
< Label MinHeight =25Margin =4VerticalAlignment =TopVerticalContentAlignment =CenterHorizo​​ntalAlignment =LeftMinWidth =100>输入5位数id< / Label>

< / StackPanel>
< / DockPanel>
< / StackPanel>

< Button Height =27Name =btnDoSomethingHorizo​​ntalAlignment =LeftVerticalAlignment =CenterMargin =4Horizo​​ntalContentAlignment =CenterClick =btnDoSomething_ClickContent =某事>
< Button.Style>
< Style TargetType ={x:Type Button}>
< Setter Property =IsEnabledValue =false/>
< Style.Triggers>
< MultiDataTrigger>
< MultiDataTrigger.Conditions>
< Condition Value =true>
< Condition.Binding>
< MultiBinding Converter ={StaticResource myConverter}>
< Binding ElementName =Grp8DigitPath =Visibility/>
< Binding ElementName =m_textBox8DigitIdPath =Validation.HasError/>
< Binding ElementName =Grp5DigitPath =Visibility/>
< Binding ElementName =m_textBox5DigitIdPath =Validation.HasError/>


< / MultiBinding>
< /Condition.Binding>
< / Condition>
< /MultiDataTrigger.Conditions>
< Setter Property =IsEnabledValue =true/>
< / MultiDataTrigger>
< /Style.Triggers>
< / Style>
< /Button.Style>
< / Button>
< / StackPanel>
< / Grid>



C#代码

  using System; 
//很多使用!
命名空间StackOverFlowBindingExample
{
///< summary>
/// Window1.xaml的交互逻辑
///< / summary>
public partial class Window1:Window,INotifyPropertyChanged
{
private static只读对象eightDigitLock = new object();
private string _eightdigitId;
public string EightDigitId
{
get
{
return _eightdigitId;
}
set
{
lock(eightDigitLock)
{
if(value!= _eightdigitId)
{
if value.Length == 8)
_eightdigitId = value;
else
抛出新的异常(必须是8位数); //我真的需要在这里抛出异常吗?

}
}
}
}

private static只读对象fiveDigitLock = new object();
private string _fivedigitId;
public string FiveDigitId
{
get
{
return _fivedigitId;
}
set
{
lock(fiveDigitLock)
{
if(value!= _fivedigitId)
{
if( value.Length == 5)
_fivedigitId = value;
else
抛出新的异常(必须是5位数); //我真的需要抛出异常吗?

}
}
}
}
public Window1()
{
InitializeComponent();
this.DataContext = this;
}
private void IdInputType_Changed(object sender,RoutedEventArgs e)
{
if(m_radio1!= null&& Grp8Digit!= null&& Grp5Digit!= null )
{
if(m_radio1.IsChecked == true)
{
Grp8Digit.Visibility = Visibility.Visible;
Grp5Digit.Visibility = Visibility.Collapsed;

}
else
{
Grp8Digit.Visibility = Visibility.Collapsed;
Grp5Digit.Visibility = Visibility.Visible;

}
}

}

private void TextBox_Error(object sender,ValidationErrorEventArgs e)
{
尝试
{
if(e.Action == ValidationErrorEventAction.Added)
{
try
{
if(e.Error.Exception!= null && e.Error.Exception.InnerException!= null&& e.Error.Exception.InnerException.Message.Length> 0)
{
((Control)sender).ToolTip = e.Error.Exception.InnerException.Message;
}
else
{
((控件)发件人).ToolTip = e.Error.ErrorContent.ToString();
}
}
catch(Exception ex)
{
string msg = ex.Message;
//Common.ProgramContext.Current.AddSessionLogEntrySync(New LogEntry(LogEntryCategory.Exception,ex.ToString()));
((Control)sender).ToolTip = e.Error.ErrorContent.ToString();
}
}
else
{
((控制)发件人).ToolTip =;
}
}
catch(异常)
{
//Common.ProgramContext.Current.AddSessionLogEntrySync(New LogEntry(LogEntryCategory.Exception,ex.ToString()) );
((Control)sender).ToolTip =;
}
}

private void btnDoSomething_Click(object sender,RoutedEventArgs e)
{

}
#region INotifyPropertyChanged成员

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{

PropertyChangedEventHandler handler = PropertyChanged;

if(handler!= null)
{

处理程序(this,new PropertyChangedEventArgs(name));

}

}
#endregion
}

public class MyConverter:IMultiValueConverter
{
public object Convert(object [] values,Type targetType,object parameter,
System.Globalization.CultureInfo culture)
{

bool valid8Digit = true;
ReadOnlyCollection< ValidationError> collection = values [1] as ReadOnlyCollection< ValidationError> ;;
if(collection!= null&& collection.Count> 0)
{
valid8Digit = false;

}
// if((bool)values [0] == true)//&&& (bool)values [1] == false)
if((Visibility)values [0] == Visibility.Visible&& valid8Digit)
{

return true ;
}
else
return false;


}

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


public class FiveByteStringConvertRule:ValidationRule
{

public override ValidationResult验证(对象值,System.Globalization.CultureInfo cultureInfo )
{
if((as as string)!= null&&(value as string).Length == 5)
return new ValidationResult(true,);
else
返回新的ValidationResult(false,);
}
}

public class EightByteStringConvertRule:ValidationRule
{

public override ValidationResult验证(对象值,System.Globalization.CultureInfo cultureInfo )
{
if((value as string)!= null&&(value as string).Length == 8)
返回新的ValidationResult(true,);
else
返回新的ValidationResult(false,);
}
}
}


解决方案

您应该使用命令来禁用/启用按钮。这是最简单和最干净的方式来做你想做的事情。



在代码隐藏文件中,声明一个新的静态类,命令,并声明一个新的RoutedUICommand。

  public static class命令
{
public static readonly RoutedUICommand DoSomething = new RoutedUICommand(Do Something ,DoSomething,typeof(MainWindow)); // MainWindow或用户控件的名称,您将要使用它。
}

要使用它,您需要在Window / UserControl中声明一个CommandBinding。

 < Window.CommandBindings> 
< CommandBinding Command =my:Commands.DoSomethingCanExecute =DoSomethingCanExecuteExecuted =DoSomethingExecuted/>
< /Window.CommandBindings>

我的是我的本地命名空间。



然后你可以简单地设置按钮来使用该命令。

 < Button Command =my:Commmands.DoSomething/ > 

CommandBinding的CanExecute和执行事件是您的逻辑应该在哪里。
要禁用/启用按钮,只需在DoSomethingCanExecute中处理。

  private void ShowXRefExecuted(object sender,ExecutedRoutedEventArgs e )
{
e.CanExecute =(Grp8Digit.Visibility == Visibility.Visible&&(...));

}

当然,执行的事件是当用户点击按钮。



编辑



验证事件仅在绑定更新时触发。要强制进行验证,您可以在window / usercontrol加载后立即更新触发器。在窗口的加载事件中:

  public void Window_Loaded(object sender,RoutedEventArgs e)
{
m_textBox8DigitId .GetBindingExpression(TextBox.TextProperty).UpdateSource();
}


I have placed below the simplest example I could come up with to demonstrate my problem. I am trying to to enable a button based on 1 of 2 conditions 1) Textbox1 is visible AND contents are valid or 2) Textbox2 is visible AND contents are valid

I seem to be on my way to enabling the button based on visibility, but the IsValid aspect is giving me grief.

For the button, I have introduced a MultiDataTrigger and MultiBinding with a MultiBinding Converter method to evaluate whether the button should be enabled or not. The method (called myConverter) is called when I switch between editboxes (by clicking a radio button), but does not seem to be called when the data in the edit box is valid, invalid, or transitions between the two. Quite possibly, I'm not correctly handling Validation.HasError

My specific questions: 1) What's the correct pattern to handle this problem? Any examples? I should say that I've simplified the problem. For example, the validation might be more than just "must be eight characters", and there could be multiple edit boxes involved (like "address" and "zip" OR "address" and "state". Thus I think I probably need the MultiBinding Converter idea but I'm open to other ideas! 2) How do I handle Validation.HasError inside my Converter method? I'm treating it as ReadOnlyCollection which is probably totally wrong! 3) I think a large part of my problems are due to the many choices to handle error info. Given that I'm using ValidationRules, should I also be throwing Exceptions from my properties that back the edit fields? Will they ever be called? Can you recommend an article showing the different ways to do validation?

I've put ALL the code below. I'd be most appreciative if someone could take a quick look and point me in the right direction. -Dave XAML code

<Window x:Class="StackOverFlowBindingExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StackOverFlowBindingExample"
Title="Window1" Height="Auto" MinWidth="500" SizeToContent="Manual" WindowStartupLocation="CenterOwner" ResizeMode="CanResizeWithGrip" >
<Window.Resources>
    <local:MyConverter x:Key="myConverter" />
    <Style x:Key="textStyleTextBox" TargetType="TextBox">
        <Setter Property="Foreground" Value="#333333" />
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="MinHeight" Value="2" />
        <Setter Property="MinWidth" Value="100" />
        <Setter Property="Margin" Value="4" />
        <Setter Property="MaxLength" Value="23" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="HorizontalAlignment" Value="Left" />


        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
                    Path=(Validation.Errors)[0].ErrorContent}" />
            </Trigger>
        </Style.Triggers>
    </Style>



</Window.Resources>
<Grid>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <StackPanel Orientation="Vertical">
                <RadioButton Name="m_radio1" Margin="4" GroupName="IdInputType" IsChecked="True" Checked="IdInputType_Changed">Use Inputtype1</RadioButton>
                <RadioButton Name="m_radio2" Margin="4" GroupName="IdInputType" IsChecked="False" Checked="IdInputType_Changed">Use Inputtype2</RadioButton>
            </StackPanel>
            <DockPanel Name="Grp8Digit">
                <Label MinHeight="25" Margin="4" VerticalAlignment="Top" VerticalContentAlignment="Center" HorizontalAlignment="Left" MinWidth="100" Width="113">Type 1 Id:</Label>
                <TextBox Height="23" Name="m_textBox8DigitId" MaxLength="8" Width="120" Style="{StaticResource textStyleTextBox}" Validation.Error="TextBox_Error">
                    <TextBox.Text>
                        <Binding>
                            <Binding.ValidatesOnExceptions>true</Binding.ValidatesOnExceptions>
                            <Binding.ValidatesOnDataErrors>true</Binding.ValidatesOnDataErrors>
    <Binding.UpdateSourceTrigger>PropertyChanged</Binding.UpdateSourceTrigger>
                            <Binding.Path>EightDigitId</Binding.Path>
                            <Binding.NotifyOnValidationError>true</Binding.NotifyOnValidationError>
                            <Binding.ValidationRules>
                                <local:EightByteStringConvertRule />
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>
                <Label MinHeight="25" Margin="4" VerticalAlignment="Top" VerticalContentAlignment="Center" HorizontalAlignment="Left" MinWidth="100">Enter 8 digit id</Label>
            </DockPanel>
            <DockPanel Name="Grp5Digit" Visibility="Collapsed">


                <StackPanel Orientation="Horizontal">
                    <Label MinHeight="25" Margin="4" VerticalAlignment="Top" VerticalContentAlignment="Center" HorizontalAlignment="Left" MinWidth="100" Width="113">Type 2 id:</Label>

                    <TextBox Name="m_textBox5DigitId" Style="{StaticResource textStyleTextBox}" MinHeight="25" Margin="4" VerticalAlignment="Top" MaxLength="23" VerticalContentAlignment="Center" HorizontalAlignment="Left" MinWidth="100" Width="100" ToolTip="Enter Type 2 id">
                        <TextBox.Text>
                            <Binding>
                                <Binding.ValidatesOnExceptions>true</Binding.ValidatesOnExceptions>
                                <Binding.Path>FiveDigitId</Binding.Path>

                                <Binding.NotifyOnValidationError>true</Binding.NotifyOnValidationError>
                                <Binding.ValidationRules>
                                    <local:FiveByteStringConvertRule />
                                </Binding.ValidationRules>
                            </Binding>
                        </TextBox.Text>
                    </TextBox>
                    <Label MinHeight="25" Margin="4" VerticalAlignment="Top" VerticalContentAlignment="Center" HorizontalAlignment="Left" MinWidth="100">Enter 5 digit id</Label>

                </StackPanel>
            </DockPanel>
        </StackPanel>

        <Button Height="27" Name="btnDoSomething" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="4" HorizontalContentAlignment="Center" Click="btnDoSomething_Click" Content="Do Something">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="IsEnabled" Value="false" />
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Value="true">
                                    <Condition.Binding>
                                        <MultiBinding Converter="{StaticResource myConverter}">
                                            <Binding ElementName="Grp8Digit" Path="Visibility" />
                                            <Binding ElementName="m_textBox8DigitId" Path="Validation.HasError" />
                                            <Binding ElementName="Grp5Digit" Path="Visibility" />
                                            <Binding ElementName="m_textBox5DigitId" Path="Validation.HasError" />


                                        </MultiBinding>
                                    </Condition.Binding>
                                </Condition>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="IsEnabled" Value="true" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>
</Grid>

C# code

using System;
// lots of usings!!!
namespace StackOverFlowBindingExample
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged
{
    private static readonly object eightDigitLock = new object();
    private string _eightdigitId;
    public string EightDigitId
    {
        get
        {
            return _eightdigitId;
        }
        set
        {
            lock (eightDigitLock)
            {
                if (value != _eightdigitId)
                {
                    if (value.Length == 8)
                        _eightdigitId = value;
                    else
                        throw new Exception("Must be 8 digits");// do I really need to throw Exception here?

                }
            }
        }
    }

    private static readonly object fiveDigitLock = new object();
    private string _fivedigitId;
    public string FiveDigitId
    {
        get
        {
            return _fivedigitId;
        }
        set
        {
            lock (fiveDigitLock)
            {
                if (value != _fivedigitId)
                {
                    if (value.Length == 5)
                        _fivedigitId = value;
                    else
                        throw new Exception("Must be 5 digits");// do I really need to throw exception?

                }
            }
        }
    }
    public Window1()
    {
        InitializeComponent();
        this.DataContext = this;
    }
    private void IdInputType_Changed(object sender, RoutedEventArgs e)
    {
        if (m_radio1 != null && Grp8Digit != null && Grp5Digit != null)
        {
            if (m_radio1.IsChecked == true)
            {
                Grp8Digit.Visibility = Visibility.Visible;
                Grp5Digit.Visibility = Visibility.Collapsed;

            }
            else
            {
                Grp8Digit.Visibility = Visibility.Collapsed;
                Grp5Digit.Visibility = Visibility.Visible;

            }
        }

    }

    private void TextBox_Error(object sender, ValidationErrorEventArgs e)
    {
        try
        {
            if (e.Action == ValidationErrorEventAction.Added)
            {
                try
                {
                    if (e.Error.Exception != null && e.Error.Exception.InnerException != null && e.Error.Exception.InnerException.Message.Length > 0)
                    {
                        ((Control)sender).ToolTip = e.Error.Exception.InnerException.Message;
                    }
                    else
                    {
                        ((Control)sender).ToolTip = e.Error.ErrorContent.ToString();
                    }
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;
                    //Common.ProgramContext.Current.AddSessionLogEntrySync(new LogEntry(LogEntryCategory.Exception, ex.ToString()));
                    ((Control)sender).ToolTip = e.Error.ErrorContent.ToString();
                }
            }
            else
            {
                ((Control)sender).ToolTip = "";
            }
        }
        catch (Exception)
        {
            //Common.ProgramContext.Current.AddSessionLogEntrySync(new LogEntry(LogEntryCategory.Exception, ex.ToString()));
            ((Control)sender).ToolTip = "";
        }
    }

    private void btnDoSomething_Click(object sender, RoutedEventArgs e)
    {

    }
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string name)
    {

        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {

            handler(this, new PropertyChangedEventArgs(name));

        }

    }
    #endregion
}

public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {

        bool valid8Digit = true;
        ReadOnlyCollection<ValidationError> collection = values[1] as ReadOnlyCollection<ValidationError>;
        if (collection != null && collection.Count > 0)
        {
            valid8Digit = false;

        }
        //if ((bool)values[0] == true)//&& (bool)values[1] == false)
        if ((Visibility)values[0] == Visibility.Visible && valid8Digit)
        {

            return true;
        }
        else
            return false;


    }

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

public class FiveByteStringConvertRule   : ValidationRule
{

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if ((value as string) != null && (value as string).Length == 5)
            return new ValidationResult(true, "");
        else
            return new ValidationResult(false, "");
    }
}

public class EightByteStringConvertRule : ValidationRule
{

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if ((value as string) != null && (value as string).Length == 8)
            return new ValidationResult(true, "");
        else
            return new ValidationResult(false, "");
    }
}
}

解决方案

You should use commands to disable/enable buttons. It's the easiest and cleanest way of doing what you wish to do.

In your code-behind file, declare a new static class, Commands, and declare a new RoutedUICommand.

public static class Commands
{
    public static readonly RoutedUICommand DoSomething = new RoutedUICommand("Do Something", "DoSomething", typeof(MainWindow)); // MainWindow or the name of the usercontrol where you are going to use it.
}

To use this, you need to declare a CommandBinding in your Window/UserControl.

<Window.CommandBindings>
    <CommandBinding Command="my:Commands.DoSomething" CanExecute="DoSomethingCanExecute" Executed="DoSomethingExecuted" />
</Window.CommandBindings>

my: is my local namespace.

Then you can simply set the button to use that command.

<Button Command="my:Commmands.DoSomething"/>

The CommandBinding's CanExecute and Executed events are where your logic should lie. To disable/enable the button, simply handle that in DoSomethingCanExecute.

private void ShowXRefExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        e.CanExecute = (Grp8Digit.Visibility==Visibility.Visible && (...) );

    }

And of course, the Executed event is what happens when the user clicks the button.

EDIT

The validation event only triggers when bindings update. To force a validation, you could update the triggers by hand as soon as the window/usercontrol has loaded. In the Window's Loaded event:

public void Window_Loaded(object sender, RoutedEventArgs e)
{
    m_textBox8DigitId.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

这篇关于基于多个属性禁用按钮。我使用MultiDataTrigger和MultiBinding的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆