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

时间:2017-02-24 10:50:24

标签: c# wpf entity-framework mvvm catel

我有一个简单的MVVM WPF应用程序,它带有数据库优先的EF dbContext(在我的应用程序中是Global.Database),它长期存在于我的应用程序中。 我有一个列表框,其中ItemsSource绑定到名为Clients的viewmodel属性的列表框,这是我的dbmodel ObservableCollection的{​​{1}}。

此列表框的Client绑定到名为SelectedItem的viewmodel属性。

SelectedClient实体类中有一个名为Client的字段,它是我数据库中的一个简单int。

因此,在我看来,当我从列表框中选择客户端时,绑定到SelectedClient的last_status的标签应该显示last_status的值。

我在viewmodel中添加了一个按钮和一个刷新命令。我想要的是:当我手动更改数据库中客户端的last_status并按我视图中的刷新按钮时,标签的内容应该更改。但我完全不知道如何实现这一目标。这是我的viewmodel代码的一部分(我使用Catel,但这种情况并不重要):

last_status

我的XAML列表框:

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();
    }

我的XAML标签:

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

还有一个按钮:

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

现在,当我在数据库中手动更改客户端的<Button Command="{Binding RefreshClientInfoCommand}" Content="↻"/> 值并按下刷新按钮时,没有任何反应。但是当我在列表框中选择另一个客户端然后返回到所需的客户端 - 标签内容更新正确。我知道,也许我想念一些非常愚蠢和简单的东西,但我无法弄明白到底是什么。也许我需要在我的按钮命令处理程序中强制更改last_status,或以某种方式调用SelectedClient的setter ... 请帮我。非常感谢。

2 个答案:

答案 0 :(得分:2)

好吧,我弄清楚我的代码出了什么问题。

我的databindig设置为SelectedClient.last_status。由于某种原因,它没有像我预期的那样工作。所以我创建了一个名为LastStatus的新viewmodel属性并修改了我的RefreshClientInfo:

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

和绑定标签到这个新属性。现在一切正常。

答案 1 :(得分:0)

您需要将SelectedClient属性设置为从EF查询中返回的新Client对象。

您可以在查询数据库之前存储当前所选客户端的client_id,然后选择具有此特定Client的新client_id对象。

试试这个:

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);
}

编辑:确保从数据库中获取更新的记录:

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]);
}