根据文本框内容更改 WPF 控件(按钮)的启用属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25789865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change enabled property of a WPF control (button) based on textbox content
提问by ck84vi
Im looking for a solution in WPF to change the IsEnabled property of a button based on the content of a textbox. The TextBox holds a numeric value. If the value is greater than a certain value the IsEnabled property of the button should be set to true, as long as it is below this value the property should be false. I have been looking around but couldn't find a proper solution. What i found here on CodeProjectis almost what im looking for. But the problem is that this approach just checks if any content is in the textbox. But i need to check/compare the numeric content.
我在 WPF 中寻找解决方案来根据文本框的内容更改按钮的 IsEnabled 属性。TextBox 包含一个数值。如果该值大于某个值,则按钮的 IsEnabled 属性应设置为 true,只要低于此值,则该属性应为 false。我一直在环顾四周,但找不到合适的解决方案。我在CodeProject上找到的几乎就是我要找的。但问题是这种方法只是检查文本框中是否有任何内容。但我需要检查/比较数字内容。
I would prefer to find a way to do it in XAML. Alternatively i could implement it also in my ViewModel. But i dont have an idea how to do it! I was thinking about to notify the button via my INotifyChanged event from the property that is shown in the textbox. But i couldnt find out how.
我更愿意在 XAML 中找到一种方法。或者,我也可以在我的 ViewModel 中实现它。但我不知道该怎么做!我正在考虑通过我的 INotifyChanged 事件从文本框中显示的属性通知按钮。但我不知道如何。
Followed some code. But, sorry, there is nothing beside the textbox and the button since i couldnt find a way to solve that.
遵循一些代码。但是,抱歉,除了文本框和按钮之外什么都没有,因为我找不到解决这个问题的方法。
<TextBox Name ="tbCounter" Text ="{Binding CalcViewModel.Counter, Mode=OneWay}" Background="LightGray" BorderBrush="Black" BorderThickness="1"
Height="25" Width="50"
commonWPF:CTextBoxMaskBehavior.Mask="Integer"
commonWPF:CTextBoxMaskBehavior.MinimumValue="0"
commonWPF:CTextBoxMaskBehavior.MaximumValue="1000"
IsReadOnly="True"/>
<Button Name="btnResetCount" Focusable="True" Content="Reset" Command="{Binding Path=CalcViewModel.ResetCounter}" Style="{StaticResource myBtnStyle}"
Width="100" Height="25">
Is there a common way to set the IsEnabled property of a control based on a property/value in the XAML or in the ViewModel?
是否有一种通用方法可以根据 XAML 或 ViewModel 中的属性/值设置控件的 IsEnabled 属性?
EDITThis is my ViewModel, i extracted the related members and properties only otherwise the post would be too long:
编辑这是我的 ViewModel,我只提取了相关的成员和属性,否则帖子会太长:
class CalcViewModel:INotifyPropertyChanged
{
private CCalc _calc;
public int Counter
{
get
{ return _calc.Counter; }
set{ _calc.Counter = value;}
}
public event PropertyChangedEventHandler PropertyChanged;
void ResetCounterExecute()
{ _calc.Counter = 0; }
bool CanResetCounterExecute()
{
if (_calc.Counter > 0)
{ return true; }
else
{ return false; }
}
public ICommand ResetCounter
{ get { return new RelayCommand(ResetCounterExecute, CanResetCounterExecute); } }
public CCalcViewModel()
{
this._calc = new CCalcViewModel();
this._calc.PropertyChanged += new PropertyChangedEventHandler(OnCalcPropertyChanged);
}
private void OnCalcPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.RaisePropertyChanged(e.PropertyName);
}
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
回答by C Bauer
You want to combine an element property binding:
你想结合一个元素属性绑定:
IsEnabled={Binding ElementName=Textbox, Path=Text}
With a valueconverter
带值转换器
IsEnabled={Binding ElementName=Textbox, Path=Text, Converter={StaticResource IsAtLeastValueConverter}}
IsAtLeastValueConverter.cs
IsAtLeastValueConverter.cs
namespace WpfPlayground
{
public class IsAtLeastValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (System.Convert.ToInt32(value) > 5)
{
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
Oh I forgot you'll need to add this to your control:
哦,我忘了您需要将其添加到您的控件中:
<Window.Resources>
<wpfPlayground:IsAtLeastValueConverter x:Key="IsAtLeastValueConverter" />
</Window.Resources>
Edit: VM Version
编辑:VM 版本
I've put in elipsis (...) where I didn't make changes to your code.
我在省略号 (...) 中没有对您的代码进行更改。
<Button ... IsEnabled={Binding Path=ButtonIsEnabled} ...>
class CalcViewModel:INotifyPropertyChanged
{
private CCalc _calc;
private bool _buttonIsEnabled;
public ButtonIsEnabled {
get { return _buttonIsEnabled; }
set {
_buttonIsEnabled = value;
RaisePropertyChanged("ButtonIsEnabled");
}
}
public int Counter
{
get
{ return _calc.Counter; }
set{
_calc.Counter = value;
_buttonIsEnabled = _calc.Counter > 5;
}
}
...
}
So what happens here is when you change the counter value, you set the ButtonIsEnabled property which raises the property changed event and updates the button on the form with whatever logic you're using to determine if the button should be enabled.
所以这里发生的事情是当您更改计数器值时,您设置 ButtonIsEnabled 属性,该属性引发属性更改事件并使用您用来确定是否应启用按钮的任何逻辑更新表单上的按钮。
Edit: You might need to remove that Binding=OneWay from the textbox, I'm not sure if it will initiate the set property if you're using that setting.
编辑:您可能需要从文本框中删除 Binding=OneWay,如果您使用该设置,我不确定它是否会启动 set 属性。
回答by David E
If you wish to do it directly in the XAML (I wouldn't necessarily recommend this, as validation should probably be done in the view model), you can also use a package, such as https://quickconverter.codeplex.com/- this allows you to write some C# (ish) in a binding.
如果您希望直接在 XAML 中执行此操作(我不一定推荐这样做,因为验证可能应该在视图模型中完成),您还可以使用一个包,例如https://quickconverter.codeplex.com/- 这允许您在绑定中编写一些 C# (ish)。
I've used it before, and it can make it pretty easy, eg you install the package, add the line to the very start of your application:
我以前使用过它,它可以使它变得非常简单,例如,您安装包,在应用程序的最开始添加以下行:
QuickConverter.EquationTokenizer.AddNamespace(typeof(object));
which adds the System namespace to QuickConverter (the line above works as object is in the System namespace), and then you can simply do:
它将 System 命名空间添加到 QuickConverter(上面的行作为对象位于 System 命名空间中),然后您可以简单地执行以下操作:
IsEnabled="{qc:Binding 'Int32.TryParse($P) && Int32.Parse($P) >= 3', P={Binding ElementName=tbCounter, Path=Text}}"
If &breaks your Intellisense, you can instead write:
如果&破坏了您的智能感知,您可以改为编写:
IsEnabled="{qc:Binding 'Int32.TryParse($P) ## Int32.Parse($P) >= 3', P={Binding ElementName=tbCounter, Path=Text}}"
(Where 3is the value you're testing against).
(3您要测试的值在哪里)。
EDIT:
编辑:
Sorry, on re-reading you XAML, it can be written even more straightforwardly as follows:
抱歉,在重新阅读您的 XAML 时,它可以更直接地编写如下:
IsEnabled="{qc:Binding '$P >= 3', P={Binding CalcViewModel.Counter}}"
回答by BRAHIM Kamel
You should change your ViewModel to something like this
你应该把你的 ViewModel 改成这样
public class ViewModel:INotifyPropertyChanged
{
public int Counter
{
get { return _counter; }
set {
_counter = value;
RaisePropChanged("Counter");
//for example
if (value>3)
{
IsButtonCounterEnabled = true;
}
else
{
IsButtonCounterEnabled = false;
}
}
}
public bool IsButtonCounterEnabled
{
get { return _IsButtonCounterEnabled; }
set { _IsButtonCounterEnabled = value;
RaisePropChanged("IsButtonCounterEnabled");
}
}
private void RaisePropChanged(string propName)
{
PropertyChanged(this,new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged = delegate{};
private int _counter;
private bool _IsButtonCounterEnabled;
}
and then Bind your button like this
然后像这样绑定你的按钮
<Button IsEnabled="{Binding IsButtonCounterEnabled,Mode=OneWay}" Content="Button" HorizontalAlignment="Left" Height="47" Margin="215,57,0,0" VerticalAlignment="Top" Width="159"/>
Hope this help
希望这有帮助

