使用Mvvm在wpf中创建SearchCommand,将新数据加载到我的列表视图中 [英] Create a SearchCommand in wpf using Mvvm that loads new data to my list view

查看:65
本文介绍了使用Mvvm在wpf中创建SearchCommand,将新数据加载到我的列表视图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以使用一些帮助,试图了解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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆