简体   繁体   English

WPF实体框架刷新一个上下文实体

[英]WPF Entity Framework refresh one context entity

I have a simple MVVM WPF app with database-first EF dbContext (which is Global.Database in my app), which is long-living in my application. 我有一个简单的MVVM WPF应用程序,其数据库优先EF dbContext(在我的应用程序中为Global.Database在我的应用程序中长期存在。 I have a window with a listbox with ItemsSource binded to viewmodel property called Clients which is an ObservableCollection of my dbmodel Client . 我有一个带有列表框的窗口,其中的ItemsSource绑定到名为Clients viewmodel属性,这是我的dbmodel ClientObservableCollection

The SelectedItem of this listbox is binded to a viewmodel property called SelectedClient . 此列表框的SelectedItem绑定到名为SelectedClient的视图模型属性。

In Client entity class there is a field called last_status which is a simple int from my database. Client实体类中,有一个名为last_status的字段,这是我数据库中的一个简单整数。

So, in my view, when i select client from listbox, a label binded to SelectedClient's last_status should show the value of last_status . 所以,在我看来,当我从列表框中选择客户端,一个标签绑定到SelectedClient的last_status应该显示的值last_status

I added a button and a refresh command into my viewmodel. 我在视图模型中添加了一个按钮和一个刷新命令。 All i want is: when i manually change last_status for the client in my database and press refresh button in my view, the content of label should change. 我想要的是:当我在数据库中手动更改客户端的last_status并在视图中按“刷新”按钮时,标签的内容应更改。 But i have absolutely no idea how to achieve this. 但是我绝对不知道如何实现这一目标。 Here is the part of my viewmodel code (i use Catel, but it doesn't matter for this case): 这是我的视图模型代码的一部分(我使用Catel,但在这种情况下并不重要):

public ClientManagerWindowViewModel()
    {

       RefreshClientInfoCommand = new Command(OnRefreshClientInfoCommandExecute);

       Clients = new ObservableCollection<Client>();
       RefreshClients();
    }

public ObservableCollection<Client> Clients
    {
        get { return GetValue<ObservableCollection<Client>>(ClientsProperty); }
        set { SetValue(ClientsProperty, value); }
    }

    public static readonly PropertyData ClientsProperty = RegisterProperty("Clients", typeof(ObservableCollection<Client>));

public Client SelectedClient
    {
        get
        {return GetValue<Client>(SelectedClientProperty);}
        set
        {
            SetValue(SelectedClientProperty, value);
        }
    }

    public static readonly PropertyData SelectedClientProperty = RegisterProperty("SelectedClient", typeof(Client));


//here is my refresh button command handler:

 public Command RefreshClientInfoCommand { get; private set; }

 private void OnRefreshClientInfoCommandExecute()
 {
     RefreshClientInfo(SelectedClient);
 }

//and here is my "logic" for working with dbcontext:

private void RefreshClients()
    {
        var qry = (from c in Global.Database.Clients where c.client_id != 1 select c).ToList();
        Clients = new ObservableCollection<Client>(qry);
    }

private void RefreshClientInfo(Client client)
    {
        Global.Database.Entry(client).Reload();
    }

My XAML for a listbox: 我的XAML用于列表框:

<ListBox
                    x:Name="ClientsListBox"
                    Grid.Row="1"
                    Margin="5"
                    DisplayMemberPath="fullDomainName"
                    IsSynchronizedWithCurrentItem="True"
                    ItemsSource="{Binding Clients}"
                    SelectedItem="{Binding SelectedClient}" />

My XAML for a label: 我的XAML标签:

<Label Margin="5" Content="{Binding SelectedClient.last_status}" />

And for a button: 对于按钮:

<Button Command="{Binding RefreshClientInfoCommand}" Content="↻"/>

For now, when i change a client's last_status value manually in database and press refresh button nothing happens. 现在,当我在数据库中手动更改客户端的last_status值并按“刷新”按钮时,没有任何反应。 But when i select another client in a listbox and then return to needed client - label content updates correctly. 但是,当我在列表框中选择另一个客户端,然后返回所需的客户端时-标签内容正确更新。 I know, maybe i miss something very stupid and simple, but i cant' figure out what exactly. 我知道,也许我想念一些非常愚蠢和简单的东西,但是我无法弄清楚到底是什么。 Maybe i need to force change SelectedClient in my button command handler, or call SelectedClient s setter somehow... Please, help me. 也许我需要在按钮命令处理程序中强制更改SelectedClient或以某种方式调用SelectedClient的设置器...请帮助我。 Thanks a lot. 非常感谢。

Well, i figured out what was wrong with my code. 好吧,我弄清楚了我的代码出了什么问题。

My databindig was set to SelectedClient.last_status . 我的databindig设置为SelectedClient.last_status For some reason it didn't work as i expected. 由于某种原因,它没有按我的预期工作。 So i created a new viewmodel property called LastStatus and modified my RefreshClientInfo: 因此,我创建了一个名为LastStatus的新viewmodel属性,并修改了RefreshClientInfo:

 private void RefreshClientInfo(Client client)
    {
        Global.Database.Entry(client).Reload();
        LastStatus = client.last_status;
        SetValue(SelectedClientProperty, client);
    }

and binded label to this new property. 并将标签绑定到此新属性。 Now everything works correct. 现在一切正常。

You need to set the SelectedClient property to the new Client object that you get back from the EF query. 您需要将SelectedClient属性设置为从EF查询返回的新Client对象。

You could do this by storing the client_id of the currently selected client before you query the database and then select the new Client object with this particular client_id . 您可以通过在查询数据库之前存储当前选定客户端的client_id来执行此操作,然后使用该特定的client_id选择新的Client对象。

Try this: 尝试这个:

private void RefreshClients()
{
    int? currentlySelectedClientId = (SelectedClient != null) ? SelectedClient.client_id : default(int?);
    var qry = (from c in Global.Database.Clients where c.client_id != 1 select c).ToList();
    Clients = new ObservableCollection<Client>(qry);
    if (currentlySelectedClientId.HasValue)
        SelectedClient = Clients.FirstOrDefault(x => x.client_id = currentlySelectedClientId.Value);
}

Edit: Make sure that you fetch the updated records from the DB: 编辑:请确保您从数据库中获取更新的记录:

private void RefreshClientInfo(Client client)
{
    var newClient = (from c in Global.Database.Clients where c.client_id == client.client_id select c).ToList();
    SetValue(SelectedClientProperty, newClient[0]);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM