Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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
Wpf 如何在主/详细方案中保持对详细信息的更改_Wpf_Mvvm_Asp.net Web Api - Fatal编程技术网

Wpf 如何在主/详细方案中保持对详细信息的更改

Wpf 如何在主/详细方案中保持对详细信息的更改,wpf,mvvm,asp.net-web-api,Wpf,Mvvm,Asp.net Web Api,我觉得这应该很简单,但我对WPF和MVVM还不熟悉,只是不知道在哪里使用MVVM。我已经搜索了wpf+master+detail+mvvm,但没有一个示例能够将数据持久化回数据库/Web服务,这正是我试图实现的 在MVVM中使用HttpClient对Web API的调用应该放在哪里?我想在用户更改TodoModel的Text属性时调用Web API,例如PUThttp://webapi.example.com/todos/5请求主体类似于{“Text”:“此文本已更新”} 型号: public

我觉得这应该很简单,但我对WPF和MVVM还不熟悉,只是不知道在哪里使用MVVM。我已经搜索了wpf+master+detail+mvvm,但没有一个示例能够将数据持久化回数据库/Web服务,这正是我试图实现的

在MVVM中使用HttpClient对Web API的调用应该放在哪里?我想在用户更改TodoModel的Text属性时调用Web API,例如
PUThttp://webapi.example.com/todos/5
请求主体类似于
{“Text”:“此文本已更新”}

型号:

public class TodoModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Text { get; set; }
}
视图:


视图模型:

public class TodoViewModel : INotifyPropertyChanged
{
    public ObservableCollection<TodoModel> Todos { get; set; }

    private TodoModel _selectedTodo;
    public TodoModel SelectedTodo 
    {
        get 
        { 
            // This triggers when changing the todo text, but it feels wrong to post changes back to the web api in a getter?!
            return _selectedTodo; 
        }
        set 
        { 
            _selectedTodo = value; 
            RaisePropertyChanged("SelectedTodo"); 
        }
    }

    private ObservableCollection<TodoModel> GetTodoModels()
    {
        // Todo models should be retrieved from a web api.
        var todos = new ObservableCollection<TodoModel>();
        todos.Add(new TodoModel { Id = 1, Title = "Lorem", Text = "Lorem ipsum dolor sit amet" });
        todos.Add(new TodoModel { Id = 2, Title = "Consectetur", Text = "Consectetur adipisicing elit" });
        todos.Add(new TodoModel { Id = 3, Title = "Sed", Text = "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua" });

        return todos;
    }

    public TodoViewModel()
    {
        Todos = GetTodoModels();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
提供模型的公共类:INotifyPropertyChanged
{
公共ObservableCollection Todos{get;set;}
private TodoModel(您选择的Todo);
public ToMododel SelectedTodo
{
得到
{ 
//这会在更改todo文本时触发,但在getter中将更改发回web api感觉是错误的?!
返回_selectedTodo;
}
设置
{ 
_selectedTodo=值;
RaisePropertyChanged(“SelectedTodo”);
}
}
私有ObservableCollection getToModels()
{
//Todo模型应该从web api中检索。
var todos=新的ObservableCollection();
添加(新TodoModel{Id=1,Title=“Lorem”,Text=“Lorem ipsum dolor sit amet”});
添加(新的TodoModel{Id=2,Title=“concertetur”,Text=“concertetur adipising elit”});
添加(新TodoModel{Id=3,Title=“Sed”,Text=“Sed do eiusmod temporal incidedut ut labore et dolore magna aliqua”});
返回待办事项;
}
public to提供模型()
{
Todos=getToModels();
}
公共事件属性更改事件处理程序属性更改;
私有void RaisePropertyChanged(字符串propertyName)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
这不是试图回答这个问题,而是试图向问题作者解释他们的问题与本网站无关

您正在将WPF与数据持久性混淆。。。这两者完全无关

Windows Primation Foundation(WPF)是为Windows客户端应用程序构建的下一代演示系统,具有令人目眩的用户体验。 另一方面:

持久数据结构是一种数据结构,在修改时始终保留其自身的早期版本

在我看来,您似乎在问如何保存分层数据,在这种情况下,WPF与这个问题完全无关

这就剩下了如何保存分层数据的主题了?在我看来,这个网站上的问题范围太广了,因为保存数据的方法太多了。要继续这个问题,您需要问一个与编程相关的问题,这个问题实际上是可以回答的


更新>>>

现在了解到您想知道将数据访问代码放置在何处,我可以继续。但是,您会注意到MVVM中没有DA(用于数据访问)。MVVM是一种开发方法或体系结构模式,它没有规定要使用的任何特定数据访问方法

话虽如此,从更标准的开发角度来看,通常将数据访问层与UI层(MVVM中的V)、业务数据模型层(MVVM中的M)和业务逻辑(MVVM中的VM)分开。这种分离可以在小型应用程序中使用文件夹,也可以在大型应用程序中使用项目。这就是所谓的


最终更新>>>

你把代码放在哪里完全取决于你自己。如前所述,MVVM中没有规定必须在何处访问数据的规则,无论数据来自web服务、数据库还是硬盘上的简单文本文件

显然,数据必须在某个阶段通过视图模型,因此在WPF应用程序中最有可能找到web服务代码的两个地方是

a) 直接在视图模型中,或
b) 在视图模型引用的服务类中


然而,因为这只是我的观点,其他人会有不同的观点,所以你的问题不可能有单一的正确答案。这就是为什么这些类型的主观问题在堆栈溢出时被认为是离题的原因。

我想你现在已经解决了你的问题,但为了帮助以后可能出现的其他人,我将尝试一下。当然,有很多方法可以做到这一点

在所有情况下,出于多种原因,您可能都应该将数据获取和持久化代码放在一个类(或facad模式、接口或类似的东西)中

你可以把“保存”按钮放在某个地方。我只是说这是一种选择…:)

简单问题的简单解决方案。 基本问题是“详细视图”与主视图的绑定过于直接。对于这个简单的例子,您的解决方案(您说“感觉不对劲”)可能是最好的,因为任何其他解决方案都会增加可能没有用处的复杂性。在一个非常简单的应用程序中,我认为可以忍受一些代码气味。如果我只是在树林里徒步走一个小时,没有人会在意我是否穿着脏兮兮的臭袜子。我不想在这次短途旅行前洗衣服

更复杂的解决方案。 我正在处理一个项目,它有一个TreeView(master)和一个DetailViewer(detail),根据TreeView中所选项目的数据类型显示不同的用户控件。代替
public class TodoViewModel : INotifyPropertyChanged
{
    public ObservableCollection<TodoModel> Todos { get; set; }

    private TodoModel _selectedTodo;
    public TodoModel SelectedTodo 
    {
        get 
        { 
            // This triggers when changing the todo text, but it feels wrong to post changes back to the web api in a getter?!
            return _selectedTodo; 
        }
        set 
        { 
            _selectedTodo = value; 
            RaisePropertyChanged("SelectedTodo"); 
        }
    }

    private ObservableCollection<TodoModel> GetTodoModels()
    {
        // Todo models should be retrieved from a web api.
        var todos = new ObservableCollection<TodoModel>();
        todos.Add(new TodoModel { Id = 1, Title = "Lorem", Text = "Lorem ipsum dolor sit amet" });
        todos.Add(new TodoModel { Id = 2, Title = "Consectetur", Text = "Consectetur adipisicing elit" });
        todos.Add(new TodoModel { Id = 3, Title = "Sed", Text = "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua" });

        return todos;
    }

    public TodoViewModel()
    {
        Todos = GetTodoModels();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}