【问题标题】:How to Achieve Lazy Binding of Tab Page Controls in WPF?WPF中如何实现标签页控件的懒绑定?
【发布时间】:2010-08-16 14:46:48
【问题描述】:

我有一个实体类。这个实体有很多属性,实体的数据以TabControl 的几个TabItems 显示给用户。我还实现了 MVVM 方法。

当屏幕首先显示给用户时,我只想绑定活动的标签页控件,并且当用户在标签页中导航时,将根据需要进行额外的单独绑定。我怎样才能做到这一点?

【问题讨论】:

标签: wpf mvvm binding lazy-loading tabcontrol


【解决方案1】:

您没有任何事情可做,这是默认行为。在选择此 TabItem 之前,不会实例化 TabItem 内容的 DataTemplate


编辑:这是一个例子:

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:Page1ViewModel}">
        <v:Page1View />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:Page3ViewModel}">
        <v:Page3View />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:Page3ViewModel}">
        <v:Page3View />
    </DataTemplate>
</Window.Resources>

...

<TabControl ItemsSource="{Binding Pages}"
            DisplayMemberPath="Title">
</TabControl>

在上面的代码中,TabControl 将根据项目类型选择适当的 DataTemplate,并仅在选择该项目时呈现它。


编辑 2:显然您想在多个页面上显示单个 ViewModel 的数据。如果你想让每个TabItem的控件延迟实例化,你需要使用每个TabItemContentTemplate属性:

<TabControl>
    <TabItem Header="Page 1">
        <TabItem.ContentTemplate>
            <DataTemplate>
                <v:Page1View />
            </DataTemplate>
        </TabItem.ContentTemplate>
    </TabItem>
    <TabItem Header="Page 2">
        <TabItem.ContentTemplate>
            <DataTemplate>
                <v:Page2View />
            </DataTemplate>
        </TabItem.ContentTemplate>
    </TabItem>
    <TabItem Header="Page 3">
        <TabItem.ContentTemplate>
            <DataTemplate>
                <v:Page3View />
            </DataTemplate>
        </TabItem.ContentTemplate>
    </TabItem>
</TabControl>

【讨论】:

  • @Thomas:非常感谢四位您的回复。你能给我一些关于这种行为的有用链接吗?
  • 不幸的是我没有任何关于它的链接......它似乎没有记录
  • @Thomas :如果我不将 DataTemplates 用于选项卡项,相同的默认惰性绑定行为是否有效?
  • 不,它仅适用于模板。有关示例,请参阅我的更新答案
  • @Thomas:感谢您的详细回复。但是我只有一个viewmodel。如何实现标签项的惰性绑定?非常感谢。
【解决方案2】:

我创建了这个适用于我们第三方 tabcontrol 的解决方案。

这个想法是在设置数据上下文时“拦截”数据上下文,将其保存以备后用,并将数据上下文设置回空。当 tabitem 获得焦点时,我们设置 datacontext 并且数据将填充到选项卡中。

作为依赖属性实现。然后只需在需要的选项卡上设置属性(不要在默认出现的选项卡上设置)

    #region SavedDataContext

    private static object GetSavedDataContext(TabItemEx tabItem)
    {
        return tabItem.GetValue(SavedDataContextProperty);
    }

    private static void SetSavedDataContext(TabItemEx tabItem, object value)
    {
        tabItem.SetValue(SavedDataContextProperty, value);
    }

    public static readonly DependencyProperty SavedDataContextProperty =
        DependencyProperty.RegisterAttached("SavedDataContext", typeof(object),
                                            typeof(Attach), new UIPropertyMetadata(null));

    #endregion

    #region LazyLoad

    public static bool GetLazyLoad(TabItemEx tabItem)
    {
        return (bool)tabItem.GetValue(LazyLoadProperty);
    }

    public static void SetLazyLoad(TabItemEx tabItem, bool value)
    {
        tabItem.SetValue(LazyLoadProperty, value);
    }

    private static readonly DependencyProperty LazyLoadProperty =
        DependencyProperty.RegisterAttached("LazyLoad", typeof(bool),
                                            typeof(Attach), new UIPropertyMetadata(false, LazyLoadPropertyChanged));

    private static void LazyLoadPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs eventArgs)
    {
        if ((bool)eventArgs.NewValue)
        {
            var tabItemEx = sender as TabItemEx;
            if (tabItemEx == null)
                return;

            tabItemEx.DataContextChanged += DataContextChanged;
            tabItemEx.GotFocus += TabGotFocus;
        }
    }


    #endregion

    private static void TabGotFocus(object sender, RoutedEventArgs e)
    {
        var tabItemEx = sender as TabItemEx;

        if (tabItemEx == null)
            return;

        tabItemEx.GotFocus -= TabGotFocus;
        tabItemEx.DataContext = GetSavedDataContext(tabItemEx);
        tabItemEx.IsSelected = true;
    }

    private static void DataContextChanged(object sender, DependencyPropertyChangedEventArgs eventArgs)
    {
        var tabItemEx = sender as TabItemEx;

        if (tabItemEx == null)
            return;

        SetSavedDataContext(tabItemEx, eventArgs.NewValue);

        tabItemEx.DataContextChanged -= DataContextChanged;
        tabItemEx.DataContext = null;
    }

【讨论】:

    【解决方案3】:

    标记为答案的方法有一个缺点 - TabItem 的内容在选择时总是会重新呈现。如果它很关键 - 你可以试试this

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多