按钮IsEnabled永远不会更改

时间:2015-07-16 11:20:40

标签: c# wpf xaml mvvm frontend

这是我的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>

无论用户是否在搜索按钮旁边的搜索框中键入了任何搜索文本,这都是返回true / false的函数。该函数位于另一个.cs文件中:

public bool isButtonEnabled
{
    return (SearchBox.Selection.Count > 0);
}

问题是isEnabled的值永远不会改变,它保持为真,即按钮始终保持启用状态,或者如果我更改&gt;签名,按钮始终处于禁用状态。有什么建议吗?

5 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:2)

您可以为按钮编写触发器(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>

答案 2 :(得分:1)

它与XAML没有问题,它的通知问题。我希望你知道INotifyProperty接口的NotifyPropertyChanged事件。只有在ViewModel中为属性触发了该属性时,UI才会获取通知并对其进行更新。

如果SearchBox.Selection计数发生变化,它不会触发任何IsSearchCriteriaHasValue属性的通知,表明它已被更改并且UI应该更新。

让我们说SearchBox.Selection绑定到observableCollection并且集合发生变化,然后订阅observableCollection以进行添加/删除然后触发NotifyPropertyChanged("IsSearchCriteriaHasValue");那里。

答案 3 :(得分:1)

绑定适用于属性更改事件。您的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();
            }
        }
    }
}

}

答案 4 :(得分:-1)

绑定适用于属性更改事件。您的ViewModel应该实现INotifyPropertyChanged接口。而且你需要在属性集中提升属性更改事件。或者,您只需使用delegate command并在CanExecute方法中写入启用禁用逻辑。 请参阅此链接以获取更多信息 http://www.codeproject.com/Questions/179129/MVVM-Enable-Disable-button-via-a-PropertyChanged-e