我所做的是使用您的 MultiTrigger 解决方案,但在我的情况下,我希望仅当 3 个文本框的长度为零时才激活按钮,因此我的解决方案适用于以下代码..
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text.Length, ElementName=activationKeyTextbox}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text.Length, ElementName=serialDayStartbox}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text.Length, ElementName=serialNumdaysbox}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
我不会实现 IMultiValueConverter,因为我们在这里没有转换任何东西。 BindingGroup 可以满足您的目的。
使用 MVVM/INotifyPropertyChanged 的同样有效的方法如下:-
我知道这是旧的,但我有类似的需求,不想编写绑定组和验证...注意这是我的第一个 wpf 应用程序,也是第一次使用 mvvm!
<Button Name="AddBtn" Content="Add" Grid.Row="2" Grid.Column="2" Height="30" Width="100" Command="{Binding AddCmd}" CommandParameter="{Binding Pending}" >
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource multiButtonEnabled}" >
<Binding ElementName="tb1" Path="(Validation.Errors)[0]" />
<Binding ElementName="tb2" Path="(Validation.Errors)[0]" />
<Binding ElementName="tb3" Path="(Validation.Errors)[0]" />
</MultiBinding>
</Button.IsEnabled>
</Button>
转换器看起来像这样
[ValueConversion(typeof(ValidationError), typeof(bool))]
class TxtBoxMultiEnableConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
int i=0;
foreach (var item in values)
{
if (item as ValidationError != null)
{
i++;
}
}
if (i!=0)
{
return false;
}
return true;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
我正在使用 IDataErrorInfo 来捕获模型中的错误,并绑定到一个双精度数。 WPF 很好,在绑定时会为您抛出解析错误,但它们并没有真正为您提供挂钩它们以更改显示给用户的消息或为您提供一个属性来检查是否有错误标记的方法很烦人,但这使您可以捕获解析中的错误,而不必检查验证规则中的解析错误。我敢肯定我的无知正在表现出来,但我们都必须从某个地方开始!
正如迈克所说,文本框没有改变。
您可能应该绑定 textbox.Text 属性。
在你的例子中:
<Button Content="Action" Click="Action_Click" >
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource ValCon}">
<Binding ElementName="textBox1" Path="Text"/>
<Binding ElementName="textBox2" Path="Text" />
<Binding ElementName="textBox3" Path="Text"/>
<Binding ElementName="textBox4" Path="Text"/>
</MultiBinding>
</Button.IsEnabled>
</Button>
这是我的第一个 StackOverflow 答案,所以它可能不准确或需要调整以遵循 StackOverflow 协议。
至于这条评论:https://stackoverflow.com/a/23504690/14654255(无法直接评论)
我已经尝试使用这个建议;但是,没有另一种机制来手动更新 MultiBinding 是不够的。 我的建议是:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApp.Converters
{
/// <summary>
/// This class will be used to determine whether the form submission button should be enabled
/// </summary>
[ValueConversion(typeof(Control), typeof(bool))]
public class FormConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
foreach (Control control in values)
{
//Relevant inside the scope of the current iteration only
string text = null;
//Any validation error
if (Validation.GetHasError(control))
return false;
//No value selected
if (control is DatePicker datePicker)
if (datePicker.SelectedDate == DateTime.Today)
return false;
else continue;
if (control is ComboBox comboBox)
if (comboBox.SelectedIndex == -1)
return false;
else continue;
//Left blank
if (control is TextBox textBox)
text = textBox.Text;
else if (control is PasswordBox passwordBox)
text = passwordBox.Password;
if (text != null && text.Length == 0)
return false;
}
return true;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApp
{
class MainWindow : Window
{
private MultiBindingExpression buttonBinding = null;
public MainWindow()
{
InitializeComponent();
buttonBinding = BindingOperations.GetMultiBindingExpression(button, button.IsEnabledProperty);
}
private void UpdateButton(object sender, RoutedEventArgs e)
{
if (registerButtonBinding == null)
return;
buttonBinding.UpdateTarget();
}
}
}
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:WpfApp.Converters">
<Window.Resources>
<converters:formConverter x:Key="formConverter"/>
</Window.Resources>
<StackPanel HorizontalAlignment="Center">
<TextBlock Text="First name"/>
<TextBox x:Name="firstNameTextBox"/>
<Button x:Name="button">
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource formConverter}">
<Binding ElementName="firstName"/>
</MultiBinding>
</Button.IsEnabled>
</Button>
</StackPanel>
</Window>