WPF Datagrid绑定不会更新直到单击行标题 [英] WPF Datagrid Binding Doesn't Update Until Clicking Row Header

查看:241
本文介绍了WPF Datagrid绑定不会更新直到单击行标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在视图模型中绑定到列表的数据网格。在我点击行标题之前,网格的内容不会更新。点击各种单元格不影响它。我必须点击标题。



这是XAML中的datagrid:

 < DataGrid x:Name =TransactionDetailsGridGrid.Row =1AutoGenerateColumns =FalseSelectionMode =ExtendedIsReadOnly =TrueHeadersVisibility =Column
ItemsSource ={ Binding TransactionDetailList}SelectedItem ={Binding SelectedTransactionDetail}GridLinesVisibility =None>
< DataGrid.Columns>
< DataGridTextColumn Binding ={Binding Path = Account.AccountNumber}标题=帐号 HeaderStyle ={StaticResource DataGridHeaderStyleCenter}Width =120/>
< DataGridTextColumn Binding ={Binding Path = Account.AccountName}Header =Account NameHeaderStyle ={StaticResource DataGridHeaderStyleCenter}Width =*/>
< DataGridTextColumn Binding ={Binding Path = Amount}Header =AmountHeaderStyle ={StaticResource DataGridHeaderStyleCenter}Width =120/>
< /DataGrid.Columns>
< / DataGrid>

这是来自视图模型:

  public List< TransactionDetail> TransactionDetailList 
{
get {return this._transactionDetailList; }

set
{
this._transactionDetailList = value;
RaisePropertyChanged(TransactionDetailList);
}
}

这是其中一个项目的编辑,视图模型:

  private void AddTransactionDetail()
{
TransactionDetailViewModel viewModel = new TransactionDetailViewModel();

MainWindowViewModel.ViewLoader.ShowDialog(viewModel);

if(viewModel.TransactionDetail!= null)
{
this.TransactionDetailList.Add(viewModel.TransactionDetail);
RaisePropertyChanged(TransactionDetailList);
}
}

运行后,我可以在getDetailDetailList,并且该集合中有该项。但是,datagrid为空。如果我点击标题行,该项目将显示在网格中。



在进行编辑时,我有同样的问题。



我以前成功了,所以我不知道这里有什么不同。我错过了什么吗?为什么在点击标题行之前,网格不会显示其内容?



我刚刚注意到有趣的事情。当我点击网格标题时,TransactionDetailList getter中的断点不会被击中,但数据仍然显示。所以,它就像网格有信息,只是直到标题被点击才显示。



在更改为使用ObservableCollection之后,它工作。但现在我和编辑有同样的问题(网格直到点击标题才能更新):

  private void EditTransactionDetail()
{
TransactionDetailViewModel viewModel = new TransactionDetailViewModel(this.SelectedTransactionDetail);

MainWindowViewModel.ViewLoader.ShowDialog(new TransactionDetailViewModel(this.SelectedTransactionDetail));

RaisePropertyChanged(TransactionDetailList);
}

我的实体需要实现INotifyPropertyChanged吗?如果我更改集合,并调用RaisePropertyChanged,那不应该导致更新网格?

解决方案

问题是当您从集合中添加或删除项目时,不会调用setter。这意味着 INotifyPropertyChanged 不被调用,视图无法知道需要刷新。



WPF通过支持 INotifyCollectionChanged 接口来解决这个问题。



尝试使用 ObservableCollection< TransactionDetail> ; 而不是列表< TransactionDetail> ObservableCollection< T> 内置,并实现 INotifyCollectionChanged ,所以你不必对代码做很多。



还要确保您继续在您的视图模型上实现 INotifyPropertyChanged 。这样,当您更换整个集合(调用setter)时,该视图将被通知。

  public ObservableCollection< TransactionDetail> TransactionDetailList 
{
get {return this._transactionDetailList; }

set
{
this._transactionDetailList = value;
RaisePropertyChanged(TransactionDetailList);
}
}

请参阅:





修改



此外,您应该实现 INTifyPropertyChanged TransactionDetail 也。如果你不能,将它包装在一个实现 INotifyPropertyChanged 的类中。



如果你不实现它在 TransactionDetail ,而不是不影响列表的更改,但对 TransactionDetail 实例的影响属性如果您尝试通过调用 RaisePropertyChanged

$ c>在列表属性,那么你的UI认为整个列表(因此整个UI对象)需要抛出和更新。这样会使你的表现受到影响,使您的应用程序缓慢下来。


I have a datagrid that is bound to a List in the view model. The grid's contents don't update until I click on the row header. Clicking in various cells doesn't affect it. I have to click on the header.

This is the datagrid in the XAML:

<DataGrid x:Name="TransactionDetailsGrid" Grid.Row="1" AutoGenerateColumns="False" SelectionMode="Extended" IsReadOnly="True" HeadersVisibility="Column"
                  ItemsSource="{Binding TransactionDetailList}" SelectedItem="{Binding SelectedTransactionDetail}" GridLinesVisibility="None">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=Account.AccountNumber}" Header="Account No." HeaderStyle="{StaticResource DataGridHeaderStyleCenter}" Width="120" />
        <DataGridTextColumn Binding="{Binding Path=Account.AccountName}" Header="Account Name" HeaderStyle="{StaticResource DataGridHeaderStyleCenter}" Width="*" />
        <DataGridTextColumn Binding="{Binding Path=Amount}"  Header="Amount" HeaderStyle="{StaticResource DataGridHeaderStyleCenter}" Width="120" />
    </DataGrid.Columns>
</DataGrid>

And this is from the view model:

public List<TransactionDetail> TransactionDetailList
{
    get { return this._transactionDetailList; }

    set
    {
        this._transactionDetailList = value;
        RaisePropertyChanged("TransactionDetailList");                
    }
}

This is the edit of one of the items, in the view model:

private void AddTransactionDetail()
{
    TransactionDetailViewModel viewModel = new TransactionDetailViewModel();

    MainWindowViewModel.ViewLoader.ShowDialog(viewModel);

    if (viewModel.TransactionDetail != null)
    {
        this.TransactionDetailList.Add(viewModel.TransactionDetail);
        RaisePropertyChanged("TransactionDetailList");
    }
}

After this runs, I can put a breakpoint on the getter of TransactionDetailList, and the collection has the item in it. However, the datagrid is empty. If I click on the header row, the item shows up in the grid.

I have the same issue when doing an edit.

I've done this successfully before, so I'm not sure what's different here. Am I missing something obvious? Why won't the grid show its contents until I click on the header row?

I just noticed something interesting. When I click on the grid header, the breakpoint in the TransactionDetailList getter doesn't get hit, but the data still shows up. So, it's like the grid has the info, it's just not showing it until the header is clicked.

After changing to use ObservableCollection, it worked. But now I'm having the same problem with the edit (grid doesn't update until clicking the header):

private void EditTransactionDetail()
{
    TransactionDetailViewModel viewModel = new TransactionDetailViewModel(this.SelectedTransactionDetail);

    MainWindowViewModel.ViewLoader.ShowDialog(new TransactionDetailViewModel(this.SelectedTransactionDetail));

    RaisePropertyChanged("TransactionDetailList");
}

Does my entity need to implement INotifyPropertyChanged? If I change the collection, and call RaisePropertyChanged, shouldn't that cause an update to the grid?

解决方案

The problem is that when you add or remove an item from the collection, the setter isn't called. This means INotifyPropertyChanged isn't called, and the view has no way of knowing it needs to be refreshed.

WPF solves this by also supporting the INotifyCollectionChanged interface.

Try using an ObservableCollection<TransactionDetail> instead of a List<TransactionDetail>. ObservableCollection<T> is built in, and implements INotifyCollectionChanged, so you won't have to do much to your code.

Also make sure that you continue to implement INotifyPropertyChanged on your view model as you already have. This way the view will be notified when you replace the entire collection (when the setter is called).

public ObservableCollection<TransactionDetail> TransactionDetailList
{
    get { return this._transactionDetailList; }

    set
    {
        this._transactionDetailList = value;
        RaisePropertyChanged("TransactionDetailList");                
    }
}

See:

Edit:

Also, you should implement INotifyPropertyChanged on TransactionDetail too. If you can't, wrap it in a class that does implement INotifyPropertyChanged.

If you don't implement it on TransactionDetail, than changes you make that don't impact the list, but do impact properties on a TransactionDetail instance, won't show in the UI until you somehow refresh the whole list.

If you tried to fix this by calling RaisePropertyChanged on the list property, then your UI thinks the entire list (and hence the whole set of UI objects) needs to be thrown out and updated. This will kill your performance and make your app sluggish.

这篇关于WPF Datagrid绑定不会更新直到单击行标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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