MVVM与属性结合的奇怪行为

  • 本文关键字:属性 结合 MVVM c# wpf mvvm
  • 更新时间 :
  • 英文 :


我是MVVM中的初学者。我正在编写名为会员的简单应用。这是我的会员类(模型(:

class Member: INotifyPropertyChanged
{
    public Member(string name)
    {
        Name = name;
        _infoCommand = new InfoCommand(this);
    }
    string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name= value;
            notify("Name");
            notify("CanShowInfo");
        }
    }
    public override string ToString()
    {
        return Name;
    }
    public event PropertyChangedEventHandler PropertyChanged;
    void notify(string property_name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property_name));
        }
    }
    private ICommand _infoCommand;
    public ICommand InfoCommand
    {
        get
        {
            return _infoCommand;
        }
        set
        {
            _infoCommand = value;
        }
    }
    public bool CanShowInfo
    {
        get
        {
            return _infoCommand.CanExecute(null);
        }
    }
}

这是我的Infocommand类:

class InfoCommand : ICommand
{
    Member _member;
    public InfoCommand(Member member)
    {
        _member = member;
    }
    public bool CanExecute(object parameter)
    {
        if (_member.Jmeno.Length > 0)
            return true;
        else
            return false;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        MessageBox.Show("I am " + _member.Name);
    }
}

这是我的成员视图模型类:

class MembersViewModel : INotifyPropertyChanged
{
    ObservableCollection<Member> _members = new ObservableCollection<Member>();
    public MembersViewModel()
    {
        Members.Add(new Member("Member1"));
        Members.Add(new Member("Member2"));
        Members.Add(new Member("Member3"));
        Members.Add(new Member("Member4"));
        Members.Add(new Member("Member5"));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void notify(string property_name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property_name));
    }
    Member _selectedMember;
    public Member SelectedMember
    {
        get
        {
            return _selectedMember;
        }
        set
        {
            _selectedMember= value;
            notify("SelectedMember");
        }
    }
    public ObservableCollection<Member> Members
    {
        get
        {
            return _members;
        }
        set
        {
            _members = value;
        }
    }
    AddCommand _addCommand;
    public AddCommand AddCommand
    {
        get
        {
            if (_addCommand == null)
                _addCommand = new AddCommand(this);
            return _addCommand;
        }
    }
}

这是我的addCommand:

类AddCommand:icommand { 成员ViewModel _vm;

    public AddCommand(MembersViewModel vm)
    {
        _vm = vm;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        _vm.Members.Add(new Member("New Member")); //<-------------------------
    }
}

最后我的观点:

<Window x:Class="mvvm_gabriel.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="clr-namespace:mvvm_gabriel.ViewModel"
    Title="MainWindow" Height="482" Width="525">
<Window.Resources>
</Window.Resources>
<Window.DataContext>
    <ViewModels:MembersViewModel />
</Window.DataContext>
<Grid>
    <ListView ItemsSource="{Binding Members}" 
              SelectedItem="{Binding SelectedMember, Mode=TwoWay}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Name}" />
                    <Button Grid.Column="1" Content="Info" Width="50" HorizontalAlignment="Left" Command="{Binding InfoCommand}" IsEnabled="{Binding Path=CanShowInfo, Mode=OneWay}" />
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <TextBox Text="{Binding SelectedMember.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <Button Content="Add" Command="{Binding AddCommand}" />
</Grid>

当我单击ListView中的某些成员时,他的名字在文本框中显示。现在,我可以自动更新我的成员对象的名称和属性。当我完全删除某些成员的名称(String.length == 0(时,禁用了我的成员模板中的信息按钮。

我还可以通过单击添加按钮来添加新成员。成员被添加到我可观察的集合中,并在ListView自动显示。

一切都在这里效果完美。

但现在:查看我的addCommand.ecute方法中标记为<----------------------的行。当我将新成员添加到我的收藏中时,我会自动给他起名字"新成员",一切正常。然后,我可以按照上述自动禁用我的会员名称,并且我的按钮被自动禁用。但是,当我将空字符串作为标记行中构造函数中的新成员的名称时,我的信息按钮退出了工作。我可以给我的新成员任何名称,并且我的信息按钮仍然被禁用。

任何人都可以解释并建议一些解决方案,请?

MainWindow中的您的按钮将按钮的等级绑定到模型中的属性,但是命令绑定还会导致按钮询问命令的canexecute((。

<Button Grid.Column="1" Content="Info" Width="50" HorizontalAlignment="Left" Command="{Binding InfoCommand}" IsEnabled="{Binding Path=CanShowInfo, Mode=OneWay}" />

这可能会导致令人困惑的行为,如您所见。

您基本上可以删除按钮的类似绑定,然后将属性更改的处理程序添加到Infocommand。

public class InfoCommand : ICommand
{
    Member _member;
    public InfoCommand(Member member)
    {
        _member = member;
        _member.PropertyChanged += _member_PropertyChanged;
    }
    private void _member_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Name")
            RaiseCanExecuteChanged();
    }
    private void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
    public bool CanExecute(object parameter)
    {
        if (_member.Name.Length > 0)
            return true;
        else
            return false;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        MessageBox.Show("I am " + _member.Name);
    }
}

最新更新