使用Mvvm在wpf中创建SearchCommand,将新数据加载到我的列表视图中 [英] Create a SearchCommand in wpf using Mvvm that loads new data to my list view
问题描述
我可以使用一些帮助,试图了解Mvvm在Wpf中命令的工作方式以及如何将按钮绑定到它.阅读了很多有关命令和wpf的文章,但是它们似乎都不同.
I could use some help, trying to understand how the commands works in Wpf with Mvvm and how you bind a button to it. Have read a lot articles about commands and wpf, but they all seem to be different.
我已经使用mvvm模式创建了一个wpf项目.有一个将充满客户的列表视图.
I have created a wpf project using mvvm pattern. Have a list view that will get filled with customers.
现在我要执行搜索命令,因此可以在列表视图中更改数据.
Now I want to make a search command, so I can change the data in the list view.
CustomerViewModel
public class CustomerViewModel : INotifyPropertyChanged, ICommand
{
private List<Customer> CustomerList;
public CustomerViewModel()
{
CustomerList = LoadCustomerData();
}
public List<Customer> LoadCustomerData()
{
List<Customer> data = new List<Customer>();
data.Add(new Customer() { Id = 1, FirstName = "Alexander", LastName = "Malkovich", PhoneNumber = "43215678", Email = "AlexanderMalkivich@gmail.com" });
data.Add(new Customer() { Id = 2, FirstName = "Mikkel", LastName = "Larsen", PhoneNumber = "87654321", Email = "MikkelLarsen@gmail.com" });
return data;
}
public List<Customer> CustomerDataLoadedOnSearch()
{
List<Customer> data = new List<Customer>();
data.Add(new Customer() { Id = 1, FirstName = "Ulrik", LastName = "Trissel", PhoneNumber = "35325235", Email = "UlrikTrissel@gmail.com" });
data.Add(new Customer() { Id = 2, FirstName = "Michael", LastName = "Mortensen", PhoneNumber = "14214124", Email = "Michael@gmail.com" });
return data;
}
public List<Customer> Customer
{
get
{
return CustomerList;
}
}
// Search Command
#region INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
基本上,我在ctor中运行LoadCustomerData(),并使用get方法获取CustomerList.
Basically I run the LoadCustomerData() in the ctor, and gets the CustomerList with the get method.
我正在尝试创建一个搜索命令,该命令将运行另一种方法(CustomerDataLoadedOnSearch),然后在视图中再次触发get调用.
I'm trying to create a search command, that will run the other method (CustomerDataLoadedOnSearch), and then trigger the get call again in the view.
XML查看代码:
<StackPanel Orientation="Vertical">
<Button Command="{Binding SearchCommand}" Padding="15, 5" HorizontalAlignment="Right">Search</Button>
</StackPanel>
<GroupBox Header="Customers">
<StackPanel Margin="10, 10" Orientation="Vertical">
<ListView Height="250" Width="Auto" ItemsSource="{Binding Customer}" Grid.Row="1">
<ListView.View>
<GridView >
<GridViewColumn Header="ID" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" TextAlignment="Right" Width="40"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Header="First name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="Last name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding PhoneNumber}" Header="Phone" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Email}" Header="Email" Width="200"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</GroupBox>
已绑定一个名为SearchCommand的命令.现在我不确定下一步该怎么做.我是否应该创建一个名为Command的文件夹,并在其中保存我所做的所有按钮的所有命令?
Have binded a command called SearchCommand. Now I'm not so sure what to do next. Should I create a folder called Command and keep all commands in there for all my buttons I make?
还是应该将所有ICommand代码保留在ViewModel中? 希望有人可以告诉我这是如何工作的.
Or should I keep all the ICommand code in the ViewModel? Hope someone can show me how this works.
美好的一天.
更新:
到目前为止,感谢您的答复.
So far, thanks for your replys.
我设法实现了ViewModelBase& RelayCommand类.此外,我已经实现了搜索按钮的Icommand,但是当我单击它时,它会清除列表(视图失去了它的客户).
I managed to implement the ViewModelBase & RelayCommand class. Futhermore I have implemented the Icommand of the search button, but when i click it, it clears the list (the view loses its customers).
void SearchCommand_DoWork(object obj)
{
CustomerList.Clear();
CustomerList = CustomerDataLoadedOnSearch();
}
已经调试了CustomerList,当我调用CustomerDataLoadedOnSearch时,它具有两行,其中包含新客户,但是尚未填充该列表.
Have debugged the CustomerList and when I call the CustomerDataLoadedOnSearch, it have two rows with new customers inside, but the list hasen't been populated.
推荐答案
让我尝试回答这个问题,希望这对您有所帮助.
Let me try to answer this and I hope this will clear things a little bit for you.
正如sexta13所说,可以使用一些框架.我个人根本不喜欢他们.
As sexta13 said there is some frameworks you can use. Personally I don't like them at all.
我要做的是实现 RelayCommand ,我认为最简单的解决方案.
What I instead do is to implement RelayCommand, which is the easiest solution in my opinion.
继电器命令:
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Func<bool> _canExecute;
public RelayCommand(Action<object> execute, Func<bool> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute.Invoke();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
接下来,我实现如下的 ViewModelBase :
Next to that I implement ViewModelBase which looks like this:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
VerifyPropertyName(propertyName);
var handler = PropertyChanged;
if (handler == null) return;
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
private void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] != null) return;
var msg = "Invalid property name: " + propertyName;
Debug.WriteLine(msg);
}
}
有了这两个课程,您就可以开始MVVM
.
With these two classes you are ready to go MVVM
.
回到您的示例:
首先,您的private List<Customer> CustomerList;
应该是public
,而不是private
.然后应该有getter和setter.否则您的视图将无法访问.
First of all your private List<Customer> CustomerList;
should be public
and not private
. And then it should have getter and setter. otherwise it will not be reachable by your View.
public List<Customer> CustomerList{get; private set}
说到这里,那么我建议您将使用ObservableCollection<T>
而不是List<T>
.可观察的集合实现INotifyPropertyChanged
,并且每次更改集合时,您的view
都会知道.如果使用List<T>
,则必须手动告诉视图该集合已更改.
When this is said, then I will suggest that you will use ObservableCollection<T>
instead of a List<T>
. Observable collections implements INotifyPropertyChanged
, and every time your collection has changed, your view
will know. If you use List<T>
then you have to tell your view manually that the collection has changed.
完成此操作后,您可以在VM中创建命令:
When this is done then you can create a command in your VM:
public ICommand SearchCommand{get;set;}
public CustomerViewModel()
{
CustomerList = LoadCustomerData();
SearchCommand = new RelayCommand(SearchCommand_DoWork, ()=>false);
}
void SearchCommand_DoWork(object obj)
{
CustomerList.Clear();
CustomerList.Add(New Customer()); //Or iterate the search list to your collection.
}
命令分配的()=>false
部分是可选的.如果将其保留为空白,则将启用搜索按钮.如果您喜欢此示例,请使用()=>false
,它将始终被禁用.您可以使用另一个返回布尔值的属性或委托.
The ()=>false
part of the assignment of the command is optional. if you leave it blank then you search button will be enabled. if you like this example use ()=>false
it will always be disabled. You can use another attribute or delegate which returns a boolean.
这篇关于使用Mvvm在wpf中创建SearchCommand,将新数据加载到我的列表视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!