Изменить включенное свойство элемента управления (кнопки) WPF на основе содержимого текстового поля
Я ищу решение в 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">
Есть ли общий способ установить свойство IsEnabled элемента управления на основе свойства / значения в XAML или ViewModel?
РЕДАКТИРОВАТЬ Это моя 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 ответа
Вы хотите объединить привязку свойства элемента:
IsEnabled={Binding ElementName=Textbox, Path=Text}
С преобразователем стоимости
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>
Редактировать: версия VM
Я вставил elipsis (...), где я не вносил изменения в ваш код.
<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 из текстового поля, я не уверен, будет ли оно инициировать заданное свойство, если вы используете этот параметр.
Если вы хотите сделать это непосредственно в XAML (я не обязательно рекомендую это, так как проверка, вероятно, должна быть выполнена в модели представления), вы также можете использовать пакет, такой как https://quickconverter.codeplex.com/ - это позволяет вам написать C# (ish) в привязке.
Я использовал его раньше, и это может сделать это довольно легко, например, вы устанавливаете пакет, добавляете строку в самом начале вашего приложения:
QuickConverter.EquationTokenizer.AddNamespace(typeof(object));
который добавляет пространство имен System в QuickConverter (строка выше работает как объект в пространстве имен System), а затем вы можете просто сделать:
IsEnabled="{qc:Binding 'Int32.TryParse($P) && Int32.Parse($P) >= 3', P={Binding ElementName=tbCounter, Path=Text}}"
Если &
нарушает ваш Intellisense, вместо этого вы можете написать:
IsEnabled="{qc:Binding 'Int32.TryParse($P) ## Int32.Parse($P) >= 3', P={Binding ElementName=tbCounter, Path=Text}}"
(Куда 3
это значение, с которым вы тестируете).
РЕДАКТИРОВАТЬ:
Извините, перечитывая ваш XAML, он может быть написан еще проще:
IsEnabled="{qc:Binding '$P >= 3', P={Binding CalcViewModel.Counter}}"
Вы должны изменить свою 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"/>
Надеюсь это поможет