Silverlight - MVVM: сетка данных, привязанная к ICollectionView, заполненная "ChildViewModel", не будет обновлять данные
Я не смог найти похожий случай, и я продолжаю бороться. Я довольно приверженец Silverlight и борюсь с обновлением ICollectionView. Метод Refresh на самом деле не будет обновлять данные в моей сетке данных, хотя они изменены (посмотрите это в отладчике, и после сортировки сетки данных несколько раз, наконец, будут отражены изменения). Боюсь, я полностью испортил всю конструкцию своего приложения. Я думаю, что проблема как-то связана с моим принципом "MainViewModel-ChildViewModel", который я реализовал.
Вот моя конструкция: На моей главной странице я добавил "Основную модель представления" в качестве ресурса.
<UserControl.Resources>
<vm:WorkingBasketViewModel x:Key="VMMain"/>
</UserControl.Resources>
Grid LayoutRoot затем устанавливает его текстовый текст для этой модели представления:
<Grid x:Name="LayoutRoot" DataContext="{StaticResource VMMain}" Margin="20">
........// all the content
</Grid>
В "Основной видовой модели" я определяю ObservableCollection, которая содержит данные, которые будут отображаться в сетке данных в форме CollectionViewSource. элементы ObservableCollection основаны на "ChildViewModel", который представляет фактические данные и их логику для каждого datarow. Средства. Каждый элемент, добавляемый в ObservableCollection, относится к типу "ChildViewModel". Я разработал его таким образом, потому что я собираюсь отобразить несколько "страниц с подробностями" (на основе выбранной функции или по двойному щелчку ячейки), которые затем позволят просматривать, изменять и обрабатывать данные в другом пользовательском контроле. Прямое изменение в сетке данных не допускается. Таким образом, мне нужно только передать childviewmodel на следующую страницу (или usercontrol) и передать данные и их логику.
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;
}
}
В обработчике события Completed базы данных db заполните наблюдаемую коллекцию дочерней моделью
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. Источник данных находится в списке "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
Теперь я изменяю дату в этом дочернем окне и возвращаюсь на главную страницу. По возвращении я вызываю refresh для collectionView (Requests.Refresh();) -> Но данные не обновляются. Ну, иногда это происходит, но в большинстве случаев этого не происходит, пока я не отсортирую измененный столбец таблицы данных 2-3 раза (нажмите на заголовок, чтобы отсортировать и отсортировать.. и отсортировать)
Что я делаю неправильно? Кто-нибудь может помочь? Вся конструкция грязная?
Ура Элиме
1 ответ
Я не уверен, какую именно реализацию ICollectionView вы используете, но в целом ICollectionView.Refresh() обновляет только свойство View с учетом фильтрации, сортировки и группировки. Чтобы ваш пользовательский интерфейс реализовал это изменение, вам все еще нужно реализовать INotifyPropertyChanged и вызвать событие PropertyChanged после вызова Refresh().