如何在WPF中实现标签页控件的延迟绑定?

时间:2010-08-16 14:46:49

标签: wpf mvvm binding lazy-loading tabcontrol

我有一个实体类。该实体具有许多属性,并且实体的数据在TabItems的多个TabControl中向用户显示。我还实现了MVVM方法。

当首先向用户显示屏幕时,我想仅绑定活动标签页控件,并且当用户浏览标签页时,将根据需要产生额外的单独绑定。我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:16)

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


编辑:这是一个例子:

<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的控件,则需要使用每个ContentTemplate的{​​{1}}属性:

TabItem

答案 1 :(得分:1)

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

想法是在设置时“拦截”datacontext,将其保存以供日后使用,并将datacontext设置为null。当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;
    }

答案 2 :(得分:1)

标记为答案方法有一个缺点 - TabItem的内容在选择时将始终重新呈现。如果它很重要 - 您可以尝试this