Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用MVVM实现搜索功能_C#_.net_Wpf_Mvvm - Fatal编程技术网

C# 使用MVVM实现搜索功能

C# 使用MVVM实现搜索功能,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我正在将一个C#WPF应用程序转换为MVVM模式,我有几个问题: 我有一个ViewModel绑定到一个模型,该模型的构造函数要求参数是从返回到搜索查询的JSON列表中选择单个对象的结果。 我想这意味着在执行搜索之前,我无法实例化此ViewModel 这在以前不是一个问题,因为我不需要将视图数据绑定到ViewModel,只需要从GUI收集文本值来实例化对象(模型),当所有数据都已就绪并且我准备好使用它时 对于MVVM,这是一个问题,因为我不想强制此搜索成为第一个用户操作——用户应该能够修改GUI中

我正在将一个C#WPF应用程序转换为MVVM模式,我有几个问题:

我有一个ViewModel绑定到一个模型,该模型的构造函数要求参数是从返回到搜索查询的JSON列表中选择单个对象的结果。 我想这意味着在执行搜索之前,我无法实例化此ViewModel

这在以前不是一个问题,因为我不需要将视图数据绑定到ViewModel,只需要从GUI收集文本值来实例化对象(模型),当所有数据都已就绪并且我准备好使用它时

对于MVVM,这是一个问题,因为我不想强制此搜索成为第一个用户操作——用户应该能够修改GUI中绑定到ViewModel的任何字段

处理这种情况的一些实际方法是什么?似乎我必须这样做:a)在实例化VM之前等待选择搜索结果,或b)从构造函数中删除参数,而是创建一个将在实例化VM上调用的方法,以计算/设置构造函数将设置的属性

第二个问题:我如何实现搜索功能——也就是说,在单击搜索按钮后,我如何准备结果列表?之前,我将在SearchButton_Click方法中反序列化列表,并将组合框的绑定设置为结果集合。使用MVVM时,我无法描绘返回结果列表和选择单个结果之间的状态。我是否创建一个单独的ViewModel,其中包含绑定到组合框的空目标类型列表和绑定到搜索文本框的SearchTerm属性,并从SearchButton命令ICommand填充组合框?然后如何将所选项目绑定到原始viewmodel

视图模型:

class ObjectViewModel
{
    public CustomObject data;
    public ICommand Search;

    public ObjectViewModel()
    {
        this.data = new CustomObject();
    }
}
型号:

[DataContract]
public class User
{
    [DataMember(Name = "EmailAddress")]
    public string EmailAddress { get; set; }
    [DataMember(Name = "FirstName")]
    public string FirstName { get; set; }
    [DataMember(Name = "FullName")]
    public string FullName { get; set; }
    ...
}


[DataContract]
public class CustomObject
{
    public User Owner;
    ...
}
视图(尚未重写):


OwnerLookUp_Click从Owner文本框中获取文本并返回ObservableCollection并将其绑定到OwnerMatch。OwnerMatches_SelectionChanged将Owner文本框设置为所选项目的Fullname属性


在这个场景中,我将绑定什么到ObjectViewModel中的data.Owner?

好吧,您认为将参数移出构造函数是正确的。这是有意义的,因为您的VM应该表示备份视图的数据。因此,它应该有一个下拉菜单项列表、标签字符串等。当按下search时,您可以像在MVC中一样实际执行搜索并反序列化结果

要将其放到UI上,请将ComboBox绑定到视图模型上的一个属性(即列表)。反序列化完成后,您将分配给此列表。通过分配给这个变量,您将更新UI,瞧

public class MyViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> _retrievedItems;
    private string _selectedItem;

    public ObservableCollection<string> RetrievedItems
    {
        get
        {
            return _retrievedItems;
        }
        set
        {
            _retrievedItems = value;

            OnPropertychanged("RetrievedItems");
        }
    }
    public string SelectedItem
    {
        // same as other property, but with _selectedItem
    }


    public MyViewModel()
    {
        // Do whatever you normally do to initialize the view model
    }

    public void Search(string searchParamThatWasInConstructor)
    {
        // do something to get results (deserialization)
        // var results = new JavascriptSerializer( ).Deserialize<List<string>>( searchParamThatWasInConstructor );
        // That's just a fake example

        RetrievedItems = new ObservableCollection<string>(results);
        SelectedItem = RetrievedItems.Count > 0 ? RetrievedItems[0] : string.Empty;
    }
}
公共类MyViewModel:INotifyPropertyChanged
{
私人可观察收集的检索项目;
私有字符串_selectedItem;
公共可见收集检索的项目
{
得到
{
返回已检索的项目;
}
设置
{
_retrievedItems=值;
OnPropertychanged(“RetrievedItems”);
}
}
公共字符串SelectedItem
{
//与其他属性相同,但带有_selectedItem
}
公共MyViewModel()
{
//执行您通常执行的任何操作来初始化视图模型
}
public void Search(字符串searchParamthatUnconstructor)
{
//执行某些操作以获得结果(反序列化)
//var results=new JavascriptSerializer();
//那只是个假的例子
RetrievedItems=新的ObservableCollection(结果);
SelectedItem=RetrievedItems.Count>0?RetrievedItems[0]:string.Empty;
}
}
并按如下方式绑定您的组合框:

<ComboBox ItemsSource="{Binding RetrievedItems}" SelectedItem="{Binding SelectedItem}" />

视图模型应表示视图的业务逻辑和状态。因此,关于第一个问题,如果视图的有效状态是不进行搜索,那么它不应该是视图模型的构造函数参数。相反,它应该是一个财产

通常在WPF中,您会通过命令将按钮绑定到视图模型上某种类型的
ICommand
(我通常使用
DelegateCommand
)。该命令应执行搜索,然后适当地更新视图模型的状态。也就是说,它应该执行搜索,收集结果,并使用收集的数据设置与搜索结果相关的属性值

这里的好处是,假设您有一些绑定到这些搜索结果的UI组件,只要您的命令完成,您的UI就会自动刷新,而不需要额外的代码

更新

回应您的评论:所有内容都应该绑定到您的视图模型,并且您的视图模型使用这些绑定来完成它需要的工作和更新视图

因此,您的文本框
Owner
应绑定到属性,然后您的
ICommand
将如下所示:

private void ClickCommandExecute() 
{
      var results = searchHelper.SearchFor(this.Owner);
      this.ComboSource = results;
}
同样,组合框的
SelectedValue
属性将绑定到视图模型上的另一个属性。在属性的setter中,可以对选择更改作出反应:

public string SelectedResult
{
    get { ... }
    set 
    {
        _selectedResult = value;
        OnSelectedResultChanged(); // Go do what you need to do here
    }
 }

哥们,太多的文字和没有样本代码。我不会通读这一切。顺便说一句,MVVM不是问题,非MVVM是。谢谢你的回复!我不认为这完全回答了我的第二个问题。用户必须从结果中选择一个项目——我认为这意味着我需要有两个命令并将列表存储在ViewModel中。请参阅用代码更新的问题。@Yevgeniy更新了我的答案谢谢!请参阅用代码更新的问题——我绑定到(在您的示例中)MyViewModel的哪个包含所选结果的UI控件?查看我发布的更新代码;这应该可以回答这个问题。
public string SelectedResult
{
    get { ... }
    set 
    {
        _selectedResult = value;
        OnSelectedResultChanged(); // Go do what you need to do here
    }
 }