【问题标题】:How can I lazy load my view model properties when bound to a tab control?绑定到选项卡控件时如何延迟加载视图模型属性?
【发布时间】:2016-09-20 04:42:11
【问题描述】:

我在我的 WPF 应用程序中使用 MVVM,在主/详细类型场景中,我有一个搜索结果列表(主)。当用户选择结果时,我调用 Refresh 并传递数据库密钥以加载详细信息。细节是具有一些复杂属性的视图模型。这些属性中的每一个都有一个项目列表(表示数据库中的数据)以及其他一些 ICommand 和属性。

我的视图有一个选项卡控件,其中每个选项卡显示这些复杂属性之一的数据。如果用于查看数据的选项卡项被选中(可见?),我只想加载复杂属性的列表(调用 LoadItems() 方法)。

这是一个简短的例子:

public class MyItem{
    public string Id{get;set;}
    public DateTime Timestamp{get;set;}
}

public class ComplexClass:INotifyPropertyChanged
{
    private Guid _key;
    private List<MyItem> _items;

    public string Name{get;set;}
    public List<MyItem> Items 
    {
        get{
            if (_items == null) LoadItems(_key);
            return _items;
        }
        set{
            if(Equals(value, _items) return;
            _item = value;
            OnPropertyChanged("Items");
        }
    }
    public void LoadItems(Guid key){
    ... //code to load Items from database based on the key.
    }
    public ComplexClass(string name, Guid key){
        Name = name;
        _key = key;
    }
}

public class MyViewModel:INotifyPropertyChanged
{
    private ComplexClass _currentItems;
    public ComplexClass CurrentItems 
    {
        get{return _currentItems;}
        set{
            if(Equals(value, _currentItems) return;
            _currentItem = value;
            OnPropertyChanged("CurrentItems");
        }
    }
    private ComplexClass _historyItems;
    public ComplexClass HistoryItems
    {
        get{return _historyItems;}
        set{
            if(Equals(value, _historyItems) return;
            _historyItems= value;
            OnPropertyChanged("HistoryItems");
        }
    }

    public void Refresh(Guid key){
        CurrentItems = new ComplexClass("Foo", key);
        HistoryItems = new ComplexClass("Bar", key);
    }
}

这里是一些示例 XAML(假设 TabControl 的 DataContex 是 ViewModel 的一个实例)。

... 
<TabControl>
    <TabItem Header="Current Items"
        DataContext={Binding CurrentItems}>
        ...
        <ItemsControl ItemsSource={Binding Items}>
            ....
        </ItemsControl>
    </TabItem>
    <TabItem Header="History Items"
        DataContext={Binding HistoryItems}>
        ...
        <ItemsControl ItemsSource={Binding Items}>
            ....
        </ItemsControl>
    </TabItem>
</TabControl>

这是第一次。在选择“历史项目”选项卡之前,不会调用 HistoryItems.Items Getter。

但是,如果我在 ViewModel 实例上调用 Refresh,它会在 CurrentItems 和 HistoryItems 上调用 Items getter,而不管选择了哪个选项卡。

基本上我想通过只加载所需的数据来提高性能。在大多数情况下,用户将滚动浏览搜索结果(调用 ViewModel.Refresh)查看当前项目或历史记录。如果用户更改标签,我只想加载两者。

有没有什么方法可以让我在调用 Refresh 后只能根据选择的选项卡为 CurrentItems 或 HistoryItems 调用 LoadItems?

【问题讨论】:

    标签: c# wpf mvvm tabs


    【解决方案1】:

    TabItem 元素上有一个 IsSelected 属性。

    在您的视图模型中创建两个bool 属性。将相同的属性绑定到 TabItem 元素的 IsSelected 属性。

    在选定选项卡的相应设置方法中调用LoadItems()

    希望能解决你的问题:-)

    【讨论】:

    • 这不是最优雅的解决方案,但我可以通过将 IsSelected 属性添加到 ComplexClass 来使其工作,所以我接受这个答案。我希望有一种方法可以使 TabItem 仅刷新可见的绑定(在所选选项卡上)。
    • @JeremyD 刷新绑定是指用现有的新数据刷新 UI 控件?如果是,那么您可以手动调用OnPropertyChanged("CurrentItems") 而不是LoadItems()
    • 我希望 UI 在每次调用 ViewModel.Refresh 后启动对 LoadItems 的调用,但仅针对 CurrentItems 或 HistoryItems,具体取决于所选的选项卡。我通过将 IsSelected 属性添加到 ComplexClass 使其工作。然后我在 Items getter 和 IsSelected setter 中都调用if (_items == null &amp;&amp; IsSelected) LoadItems(_key); 。我想我只是期望 TabItem 中元素的绑定不会更新,除非选择了该选项卡。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2010-12-09
    • 2017-02-20
    相关资源
    最近更新 更多