gpt4 book ai didi

c# - MVVM 绑定(bind)到属性的奇怪行为

转载 作者:行者123 更新时间:2023-12-03 10:42:39 25 4
gpt4 key购买 nike

我是 MVVM 的初学者。我正在编写一个名为 Members 的简单应用程序。这是我的成员类(模型):

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

这是我的 MemberViewModel 类:
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 : ICommand
{
成员 View 模型_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 中的某个成员时,他的名字会显示在 TextBox 中。现在我可以编辑此名称,并且我的 Member 对象的属性会自动更新。当我完全删除某些成员的名称(string.Length == 0)时,我的成员模板中的信息按钮被禁用。

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

就这里而言,一切都完美无缺。

但是现在:看看这样标记的行 <----------------------在我的 AddCommand.Execute 方法中。当我将新成员添加到我的收藏中时,我会自动给他起名为“新成员”并且一切正常。然后我可以编辑我的成员(member)姓名,并且我的按钮会自动禁用,如上所述。但是,当我在标记行的构造函数中将空字符串作为新成员的名称时,启用我的信息按钮将停止工作。我可以给我的新成员起任何名字,但我的信息按钮仍然被禁用。

谁能解释一下并提出一些解决方案,好吗?

最佳答案

主窗口中的按钮将按钮的 IsEnabled 绑定(bind)到模型中的属性,但命令绑定(bind)也会导致按钮询问命令的 CanExecute()。

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

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

您基本上可以删除按钮的 IsEnabled 绑定(bind),并将属性更改处理程序添加到 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);
}
}

关于c# - MVVM 绑定(bind)到属性的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48685058/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com