在WPF MVVM中,Datagrid的SelectedIndex在RaisePropertyChanged时设置为0。

3

我正在使用mvvm light框架,运用c# Wpf开发一个项目。

这个项目中有一个数据表格,它的SelectedIndex与ViewModel中的int类型属性进行了绑定。

DocumentViewModel:

private int _docSelectedIndex;
    public int DocSelectedIndex
    {
        get { return _docSelectedIndex; }
        set
        {

            _docSelectedIndex = value;
            RaisePropertyChanged("DocSelectedIndex");

        }
    }

视图:

<DataGrid HeadersVisibility="Column"
                  x:Name="docgrid" 
                  IsSynchronizedWithCurrentItem="True"
                  DataContext ="{Binding Document, Source={StaticResource Locator}}"
                  ItemsSource="{Binding Path=DocItems}"
                  SelectedIndex="{Binding DocSelectedIndex,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
             ...
             ...
</DataGrid>

绑定工作了!但是每当我想用新数据更新网格时,我需要调用RaisePropertyChanged("DocItems")。
这似乎会将选定的索引更改为0。我尝试将选定的索引设置回原来的值,但最终索引总是被设置为0。
这是调用RaisePropertyChanged的方法:
public void UpdateDocumentList(object sender, TypedEventArg<DocListUpdatedEvent> e) 
    {
        var temp = new List<SFODocument>(e.Value.DocumentList);
        var meta = _meta.GetPageMetaData();

        foreach (var d in temp)
        {
            foreach (int i in d.PageList) 
            {
                meta[i].docid = d.DocumentID;
                _meta.UpdateExistingMeta(meta[i]);
            }

        }
        _docItems = new ObservableCollection<SFODocument>(temp);
        RaisePropertyChanged("DocItems");
    }

如何更新datagrid并仍然保留原始的selectedIndex?

由于ItemsSource由docItems属性绑定,所有项都会被“刷新”,就像名称所示的那样,它是一个项-“源更改”。因此,对于wpf,有充分的理由从旧源中放弃选择索引。在您的情况下,ItemsSource更改后,用户可能会看到一些新的、一些旧的条目,您希望保留旧条目的索引吗?如果是这样,我会这样做:将选定的对象保留为视图模型属性,在源更改后将其内容与每个新项进行比较。如果找到了它,设置选择索引,否则保持为零。 - deafjeff
我并不是真的对这个项目本身感兴趣,但我想保持行被选中,即使在RaisePropertyChanged之后。你提到我应该在sourcechange之后设置选定的索引,这就是我正在尝试的,但无论我做什么,索引都被设置为0。 - Pets
这听起来像是索引(我猜是双向绑定)在新集合绑定到ItemSource时被覆盖为零。因此,请确保它不会被覆盖。您可以在调用RaisePropertyChanged("DocItems")之前,在ViewModel中轻松设置一个标志以防止这种情况发生。 - deafjeff
我尝试使用bool _isRaisingProperty来标记。但是在标志再次设置为false后,该值被设置为0。 - Pets
为了避免这个绑定问题,不妨创建第二个视图模型属性“initialupdateIndex”,它单向绑定到选择索引的源。这样肯定不会被重置为零。 - deafjeff
糟糕..实际上应该是"OneWay"而不是"OneWayToSource"。 - deafjeff
1个回答

0
尝试以这种方式将selectedindex设置回原始状态。
Dispatcher.BeginInvoke(new Action(() => docgrid.SelectedIndex = oldIndex), DispatcherPriority.DataBind);

如果不起作用,请尝试使用其他优先级。


感谢您的输入。我尝试了每个优先级,但最终仍然将其设置为0。 - Pets
在调用UpdateDocumentList()之后,docGrid.SelectedIndex = oldIndex可能会正常工作!(不需要BeginInvoke())确保在ItemsSource更改时不要覆盖oldIndex视图模型属性(变为零)!这是使用调试器检查的重要步骤。 - deafjeff
我已经通过调试器进行了检查,可以看到oldindex是正确的,并且它正在设置所选索引(此时仍然相同)。但在设置后,另一个调用将使用值= 0。 - Pets
堆栈中的另一个调用在哪里? - neptunao
只需在代码中找到与wpf更新过程相对应的正确位置(请参见上面我的评论 :-))。 - deafjeff
Neptunao:此调用是由外部代码(WPF-RaiseProperty)引发的。至于标记解决方案,它发生在取消标记后。 - Pets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接