【问题标题】:Silverlight - MVVM: Datagrid bound to ICollectionView filled with "ChildViewModel" wont refresh dataSilverlight - MVVM:绑定到填充有“ChildViewModel”的 ICollectionView 的 Datagrid 不会刷新数据
【发布时间】:2012-05-21 07:52:14
【问题描述】:

我还没有找到类似的案例,所以我继续努力。我是 Silverlight 的新手,并且为 ICollectionView 的刷新而苦苦挣扎。刷新方法实际上不会刷新我的数据网格中的数据,尽管它们已更改(在调试器中查看它,在对数据网格进行几次排序后,它最终会反映更改)。恐怕我完全搞砸了我的应用程序的整个结构。我认为这个问题与我实现的“MainViewModel-ChildViewModel”原理有关。

这是我的构造: 在我的主页中,我添加了一个“主视图模型”作为资源。

<UserControl.Resources>
        <vm:WorkingBasketViewModel x:Key="VMMain"/>
</UserControl.Resources>

Grid LayoutRoot 然后将它的 datacontext 设置为此视图模型:

<Grid x:Name="LayoutRoot" DataContext="{StaticResource VMMain}" Margin="20">
........// all the content
</Grid>

在“主视图模型”中,我定义了一个 ObservableCollection,它保存将以 CollectionViewSource 形式显示在数据网格中的数据。 ObservableCollection 项目基于代表实际数据的“ChildViewModel”,它是每个数据行的逻辑。 意思是:添加到 ObservableCollection 的每个项目都是“ChildViewModel”的类型。 我这样设计它是因为我将显示几个“详细信息页面”(基于选择的功能或双击单元格),然后允许查看、修改和处理另一个用户控件中的数据。不允许在数据网格中直接修改。这样,我只需要将 childviewmodel 传递到下一页(或用户控件),然后传递数据及其逻辑。

private readonly ObservableCollection<childViewModel> _requestList = new ObservableCollection<childViewModel>(); // saves list of "childviewmodel-items"
private readonly ICollectionView _requestCollectionView; // ICollectionView for _requestlist-Collection.

// In the contstructor of the "Main Viewmodel"
var cvs = new CollectionViewSource {Source = _requestList};
                    cvs.SortDescriptions.Add(new SortDescription("RPI_Priority", ListSortDirection.Ascending));
                    cvs.SortDescriptions.Add(new SortDescription("REQ_TestingDate", ListSortDirection.Ascending));
                    _requestCollectionView = cvs.View; 
LoadData(); // db-fetch (entity framework)



/// <summary>
/// Binding to DataGrid!
/// </summary>
public ICollectionView Requests //-> BINDING TO DATAGRID!
{
    get
        {
            return _requestCollectionView;
        }
}

在 db-fetch 的 Completed 事件处理程序中,用 childviewmodel 填充 observablecollection

private void requests_requestLoadingComplete(object sender, EntityResultsArgs<REQ_Request> e)
{
    if (!e.HasError)
    {

       //Fire Event on UI Thread
       Application.Current.RootVisual.Dispatcher.BeginInvoke(() =>
       {
            var o = e.Results.OrderBy(r => r.REQ_TestingDate);
            //clear request list
            _requestList.Clear();
            // add requests to collectionview
            foreach (REQ_Request r in o)
            {
                   // for each record generate a Childviewmodel entry and add it to the observable collection
                   _requestList.Add(new childviewmodel(r));
            }

        });
       }
       else
       {
           // notify if there is any error
           reportError(this,new ResultsArgs(e.Error));
       }

RaiseVMStateChanged();
}

我在主页上还有一个绑定到此 ICollectionView 的数据网格。 itemsource 是“ChildViewModel”列表。它的属性绑定吧:

<sdk:DataGrid AutoGenerateColumns="False" Grid.Row="1" ItemsSource="{Binding Path=Requests}" SelectionMode="Single">
    <sdk:DataGrid.Columns>
        <sdk:DataGridTextColumn Header="ID" Binding="{Binding REQ_ID}" Width="40" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Applikationsname" Binding="{Binding REQ_ApplicationName}" Width="250" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Typ" Binding="{Binding RET_Type}"  Width="70" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Prio" Binding="{Binding RPI_Priority}" Width="70" IsReadOnly="true" />
        <sdk:DataGridTextColumn Header="Status" Binding="{Binding RST_Status}" Width="70" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Sprache" Binding="{Binding SWL_Language}" Width="70" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Version" Binding="{Binding REQ_Version}" Width="70" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Betriebssystem" Binding="{Binding SOS_OS}" Width="150" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="DA" Binding="{Binding Dienstabteilungen}" Width="150" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="AV" Binding="{Binding AV_Fullname}"  Width="150" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Paketierer" Binding="{Binding Paketierer_Fullname}"  Width="150" IsReadOnly="true"/>
        <sdk:DataGridTextColumn Header="Paketierer QS" Binding="{Binding PaketiererQS_Fullname}" Width="150" IsReadOnly="true" />
        <sdk:DataGridTextColumn Header="Abnahmetermin" Binding="{Binding REQ_TestingDate}" Width="150" IsReadOnly="true" />
    </sdk:DataGrid.Columns>
</sdk:DataGrid>

现在所有这些都运行良好且顺利。 单击功能按钮时,我打开另一个用“Childviewmodel”实例或继承它初始化的用户控件。 (某些功能是子窗口,而其他功能则显示一个用户控件,显示所有详细信息等)

例如子窗口:

ShowChildWindow(new PkgRequestDataControl(_vm.CurrentRequest)); --> PkgRequestDataControl inherits from childviewmodel. _vm.CurrentRequest is one single instance of "childviewmodel" that is given

现在我修改这个子窗口中的日期返回主页。 返回时,我在 collectionView (Requests.Refresh();) 上调用刷新 -> 但数据不会刷新。 嗯..有时它会,但大多数时候它不会,直到我对数据网格的更改后的coloum进行了2-3次排序(单击标题进行排序和排序..和排序)

我做错了什么?任何人都可以帮忙吗?整个结构很乱吗?

干杯 伊莱姆

【问题讨论】:

    标签: silverlight mvvm icollectionview


    【解决方案1】:

    我不确定您使用的是哪种 ICollectionView 实现,但通常 ICollectionView.Refresh() 只会刷新 View 属性,并考虑过滤、排序和分组。为了让您的 UI 实现此更改,您仍然需要实现 INotifyPropertyChanged 并在调用 Refresh() 后引发 PropertyChanged 事件。

    【讨论】:

    • hmm 在 _requestCollectionView.CurrentItem 的已更改属性上尝试了 PropertyChanged,但这无济于事。 Datagrid 不会更新该行
    • 当 ViewModel 中发生更改时,您需要在 View 绑定的公共属性上引发 PropertyChanged 事件。在这种情况下,它看起来像是您的 Requests 属性。因此,您将调用 Requests.Refresh() 来重新创建 Requests 的视图属性,然后在 Requests 上引发 PropertyChanged,因为它已更改。
    • 不抱歉,这无济于事。仍然是相同的行为 -> 数据网格在排序 2 次后更新更改的行,但不直接反映更改。
    • 这是我在子窗体关闭时所做的:
    • Requests.Refresh(); this.RaisePropertyChanged(p => p.Requests); // 引发属性变化的方法
    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2010-11-22
    • 1970-01-01
    • 2012-06-24
    • 2019-07-13
    • 2013-12-17
    • 1970-01-01
    • 2012-01-10
    相关资源
    最近更新 更多