按钮 IsEnabled 永远不会改变
Button IsEnabled never changes
这是我的 Button 声明,写在 .xaml 文件中:
<dxlc:LayoutGroup Orientation="Horizontal" Margin="5,15,0,5">
<Grid MinWidth="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button
IsEnabled="{Binding IsSearchCriteriaHasValue}"
Content="Search"
MaxHeight="25"
MaxWidth="70"
ClipToBounds="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Command="{Binding SearchCommand}"/>
</Grid>
</dxlc:LayoutGroup>
此函数用于判断 returns true/false 用户是否在搜索按钮旁边的搜索框中键入了任何搜索文本。该函数在另一个 .cs 文件中:
public bool isButtonEnabled
{
return (SearchBox.Selection.Count > 0);
}
问题是 isEnabled 的值永远不会改变,它保持为真,即按钮始终保持启用状态,或者如果我更改 > 符号,按钮始终保持禁用状态。有什么建议吗?
XAML 没有问题,通知有问题。我希望您了解 INotifyProperty 接口的 NotifyPropertyChanged 事件。只有在 ViewModel 中为 属性 触发时,UI 才会收到通知并更新它。
如果 SearchBox.Selection 计数发生变化,它不会触发 IsSearchCriteriaHasValue 属性 的任何通知它已被更改并且 UI 应该更新。
假设 SearchBox.Selection 绑定到一个 observableCollection 并且集合发生变化,然后为 add/remove 订阅 observableCollection 然后触发 NotifyPropertyChanged("IsSearchCriteriaHasValue")
;那里。
IsSearchCriteriaHasValue
需要引发它更改的事件,您可以使用 INotifyPropertyChanged
接口来实现:
public class Customer : INotifyPropertyChanged
{
// INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
// Your property
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
}
绑定适用于 属性 更改的事件。您的 ViewModel 应该实现 INotifyPropertyChanged
接口。并且您需要在 属性 集合中引发 属性 changed 事件。或者您可以简单地使用 delegate command
并在 CanExecute 方法中编写启用禁用逻辑。
请参阅此 link 了解更多信息
http://www.codeproject.com/Questions/179129/MVVM-Enable-Disable-button-via-a-PropertyChanged-e
您可以为按钮编写触发器(SearchBox 看起来是一个 UI 控件)
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding Selection.Count, ElementName=SearchBox}" Value="0"> !-- You can use convertor also
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style> </Button.Style> </Button>
绑定适用于 属性 更改的事件。您的 ViewModel
应该实现 INotifyPropertyChanged
接口。
https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
一个例子:
// This form demonstrates using a BindingSource to bind
// a list to a DataGridView control. The list does not
// raise change notifications. However the DemoCustomer type
// in the list does.
public partial class Form1 : Form
{
// This button causes the value of a list element to be changed.
private Button changeItemBtn = new Button();
// This DataGridView control displays the contents of the list.
private DataGridView customersDataGridView = new DataGridView();
// This BindingSource binds the list to the DataGridView control.
private BindingSource customersBindingSource = new BindingSource();
public Form1()
{
InitializeComponent();
// Set up the "Change Item" button.
this.changeItemBtn.Text = "Change Item";
this.changeItemBtn.Dock = DockStyle.Bottom;
this.changeItemBtn.Click +=
new EventHandler(changeItemBtn_Click);
this.Controls.Add(this.changeItemBtn);
// Set up the DataGridView.
customersDataGridView.Dock = DockStyle.Top;
this.Controls.Add(customersDataGridView);
this.Size = new Size(400, 200);
}
private void Form1_Load(object sender, EventArgs e)
{
// Create and populate the list of DemoCustomer objects
// which will supply data to the DataGridView.
BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());
// Bind the list to the BindingSource.
this.customersBindingSource.DataSource = customerList;
// Attach the BindingSource to the DataGridView.
this.customersDataGridView.DataSource =
this.customersBindingSource;
}
// Change the value of the CompanyName property for the first
// item in the list when the "Change Item" button is clicked.
void changeItemBtn_Click(object sender, EventArgs e)
{
// Get a reference to the list from the BindingSource.
BindingList<DemoCustomer> customerList =
this.customersBindingSource.DataSource as BindingList<DemoCustomer>;
// Change the value of the CompanyName property for the
// first item in the list.
customerList[0].CustomerName = "Tailspin Toys";
customerList[0].PhoneNumber = "(708)555-0150";
}
}
// This is a simple customer class that
// implements the IPropertyChange interface.
public class DemoCustomer : INotifyPropertyChanged
{
// These fields hold the values for the public properties.
private Guid idValue = Guid.NewGuid();
private string customerNameValue = String.Empty;
private string phoneNumberValue = String.Empty;
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// The constructor is private to enforce the factory pattern.
private DemoCustomer()
{
customerNameValue = "Customer";
phoneNumberValue = "(312)555-0100";
}
// This is the public factory method.
public static DemoCustomer CreateNewCustomer()
{
return new DemoCustomer();
}
// This property represents an ID, suitable
// for use as a primary key in a database.
public Guid ID
{
get
{
return this.idValue;
}
}
public string CustomerName
{
get
{
return this.customerNameValue;
}
set
{
if (value != this.customerNameValue)
{
this.customerNameValue = value;
NotifyPropertyChanged();
}
}
}
public string PhoneNumber
{
get
{
return this.phoneNumberValue;
}
set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged();
}
}
}
}
}
这是我的 Button 声明,写在 .xaml 文件中:
<dxlc:LayoutGroup Orientation="Horizontal" Margin="5,15,0,5">
<Grid MinWidth="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button
IsEnabled="{Binding IsSearchCriteriaHasValue}"
Content="Search"
MaxHeight="25"
MaxWidth="70"
ClipToBounds="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Command="{Binding SearchCommand}"/>
</Grid>
</dxlc:LayoutGroup>
此函数用于判断 returns true/false 用户是否在搜索按钮旁边的搜索框中键入了任何搜索文本。该函数在另一个 .cs 文件中:
public bool isButtonEnabled
{
return (SearchBox.Selection.Count > 0);
}
问题是 isEnabled 的值永远不会改变,它保持为真,即按钮始终保持启用状态,或者如果我更改 > 符号,按钮始终保持禁用状态。有什么建议吗?
XAML 没有问题,通知有问题。我希望您了解 INotifyProperty 接口的 NotifyPropertyChanged 事件。只有在 ViewModel 中为 属性 触发时,UI 才会收到通知并更新它。
如果 SearchBox.Selection 计数发生变化,它不会触发 IsSearchCriteriaHasValue 属性 的任何通知它已被更改并且 UI 应该更新。
假设 SearchBox.Selection 绑定到一个 observableCollection 并且集合发生变化,然后为 add/remove 订阅 observableCollection 然后触发 NotifyPropertyChanged("IsSearchCriteriaHasValue")
;那里。
IsSearchCriteriaHasValue
需要引发它更改的事件,您可以使用 INotifyPropertyChanged
接口来实现:
public class Customer : INotifyPropertyChanged
{
// INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
// Your property
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
}
绑定适用于 属性 更改的事件。您的 ViewModel 应该实现 INotifyPropertyChanged
接口。并且您需要在 属性 集合中引发 属性 changed 事件。或者您可以简单地使用 delegate command
并在 CanExecute 方法中编写启用禁用逻辑。
请参阅此 link 了解更多信息
http://www.codeproject.com/Questions/179129/MVVM-Enable-Disable-button-via-a-PropertyChanged-e
您可以为按钮编写触发器(SearchBox 看起来是一个 UI 控件)
<Style TargetType="Button"> <Setter Property="IsEnabled" Value="True" /> <Style.Triggers> <DataTrigger Binding="{Binding Selection.Count, ElementName=SearchBox}" Value="0"> !-- You can use convertor also <Setter Property="IsEnabled" Value="False" /> </DataTrigger> </Style.Triggers> </Style> </Button.Style> </Button>
绑定适用于 属性 更改的事件。您的 ViewModel
应该实现 INotifyPropertyChanged
接口。
https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
一个例子:
// This form demonstrates using a BindingSource to bind
// a list to a DataGridView control. The list does not
// raise change notifications. However the DemoCustomer type
// in the list does.
public partial class Form1 : Form
{
// This button causes the value of a list element to be changed.
private Button changeItemBtn = new Button();
// This DataGridView control displays the contents of the list.
private DataGridView customersDataGridView = new DataGridView();
// This BindingSource binds the list to the DataGridView control.
private BindingSource customersBindingSource = new BindingSource();
public Form1()
{
InitializeComponent();
// Set up the "Change Item" button.
this.changeItemBtn.Text = "Change Item";
this.changeItemBtn.Dock = DockStyle.Bottom;
this.changeItemBtn.Click +=
new EventHandler(changeItemBtn_Click);
this.Controls.Add(this.changeItemBtn);
// Set up the DataGridView.
customersDataGridView.Dock = DockStyle.Top;
this.Controls.Add(customersDataGridView);
this.Size = new Size(400, 200);
}
private void Form1_Load(object sender, EventArgs e)
{
// Create and populate the list of DemoCustomer objects
// which will supply data to the DataGridView.
BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());
// Bind the list to the BindingSource.
this.customersBindingSource.DataSource = customerList;
// Attach the BindingSource to the DataGridView.
this.customersDataGridView.DataSource =
this.customersBindingSource;
}
// Change the value of the CompanyName property for the first
// item in the list when the "Change Item" button is clicked.
void changeItemBtn_Click(object sender, EventArgs e)
{
// Get a reference to the list from the BindingSource.
BindingList<DemoCustomer> customerList =
this.customersBindingSource.DataSource as BindingList<DemoCustomer>;
// Change the value of the CompanyName property for the
// first item in the list.
customerList[0].CustomerName = "Tailspin Toys";
customerList[0].PhoneNumber = "(708)555-0150";
}
}
// This is a simple customer class that
// implements the IPropertyChange interface.
public class DemoCustomer : INotifyPropertyChanged
{
// These fields hold the values for the public properties.
private Guid idValue = Guid.NewGuid();
private string customerNameValue = String.Empty;
private string phoneNumberValue = String.Empty;
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// The constructor is private to enforce the factory pattern.
private DemoCustomer()
{
customerNameValue = "Customer";
phoneNumberValue = "(312)555-0100";
}
// This is the public factory method.
public static DemoCustomer CreateNewCustomer()
{
return new DemoCustomer();
}
// This property represents an ID, suitable
// for use as a primary key in a database.
public Guid ID
{
get
{
return this.idValue;
}
}
public string CustomerName
{
get
{
return this.customerNameValue;
}
set
{
if (value != this.customerNameValue)
{
this.customerNameValue = value;
NotifyPropertyChanged();
}
}
}
public string PhoneNumber
{
get
{
return this.phoneNumberValue;
}
set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged();
}
}
}
}
}