根据文本框内容更改WPF控件(按钮)的启用属性

时间:2014-09-11 14:17:52

标签: c# wpf controls isenabled

我在WPF中寻找一个解决方案,根据文本框的内容更改按钮的IsEnabled属性。 TextBox包含数值。如果该值大于某个值,则该按钮的IsEnabled属性应设置为true,只要它低于此值,该属性应为false。 我一直在环顾四周,但无法找到合适的解决方案。我在CodeProject找到的内容几乎就是我要找的东西。但问题是这种方法只检查文本框中是否有任何内容。但我需要检查/比较数字内容。

我更愿意在XAML中找到一种方法。或者我也可以在我的ViewModel中实现它。但我不知道该怎么做!我正在考虑通过文本框中显示的属性通过我的INotifyChanged事件通知按钮。但我无法弄清楚如何。

遵循一些代码。但是,抱歉,文本框和按钮旁边没有任何内容,因为我无法找到解决问题的方法。

<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">

是否有一种常见的方法可以根据XAML或ViewModel中的属性/值设置控件的IsEnabled属性?

编辑这是我的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));
        }
    }

3 个答案:

答案 0 :(得分:3)

您想要组合元素属性绑定:

IsEnabled={Binding ElementName=Textbox, Path=Text}

使用valueconverter

IsEnabled={Binding ElementName=Textbox, Path=Text, Converter={StaticResource IsAtLeastValueConverter}}

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;
        }
    }
}

哦,我忘记了你需要把它添加到你的控件中:

<Window.Resources>
    <wpfPlayground:IsAtLeastValueConverter x:Key="IsAtLeastValueConverter" />
</Window.Resources>

编辑:虚拟机版本

我已经进行了省略号(...),但我没有对您的代码进行更改。

<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;
        }
    }
    ...
}

所以这里发生的是当您更改计数器值时,您设置ButtonIsEnabled属性,该属性引发属性更改事件并使用您正在使用的任何逻辑更新表单上的按钮以确定是否应启用该按钮

修改:您可能需要从文本框中删除Binding = OneWay,如果您正在使用该设置,我不确定它是否会启动设置属性。

答案 1 :(得分:2)

如果您希望直接在XAML中执行此操作(我不一定会建议这样做,因为验证应该在视图模型中完成),您也可以使用包,例如https://quickconverter.codeplex.com/ - 这允许你在绑定中写一些C#(ish)。

我之前使用过它,它可以让它变得非常简单,例如你安装包,在应用程序的最开头添加一行:

QuickConverter.EquationTokenizer.AddNamespace(typeof(object));

将System命名空间添加到QuickConverter(上面的行作为对象在System命名空间中),然后您可以简单地执行:

IsEnabled="{qc:Binding 'Int32.TryParse($P) &amp;&amp; Int32.Parse($P) &gt;= 3', P={Binding ElementName=tbCounter, Path=Text}}"

如果&amp;打破了您的智能感知,您可以改为:

IsEnabled="{qc:Binding 'Int32.TryParse($P) ## Int32.Parse($P) &gt;= 3', P={Binding ElementName=tbCounter, Path=Text}}"

(其中3是您正在测试的值。)

编辑:

很抱歉,在重新阅读XAML时,可以更直接地编写如下:

IsEnabled="{qc:Binding '$P &gt;= 3', P={Binding CalcViewModel.Counter}}"

答案 2 :(得分:1)

您应该将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;
}

然后像这样绑定你的按钮

 <Button    IsEnabled="{Binding IsButtonCounterEnabled,Mode=OneWay}" Content="Button" HorizontalAlignment="Left" Height="47" Margin="215,57,0,0" VerticalAlignment="Top" Width="159"/>

希望这个帮助