Как добиться ленивого связывания элементов управления вкладками в WPF? - PullRequest
4 голосов
/ 16 августа 2010

У меня есть класс сущности. Эта сущность имеет множество свойств, и данные сущности показываются пользователю в виде нескольких TabItems из TabControl. Я также реализую подход MVVM.

Когда пользователю сначала показывается экран, я хочу связать только активные элементы управления вкладками, и при переходе пользователя по страницам вкладок при необходимости будут выполняться дополнительные отдельные привязки. Как мне этого добиться?

Ответы [ 3 ]

16 голосов
/ 16 августа 2010

Вам нечего делать, это поведение по умолчанию.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 каждого TabItem:

<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>
1 голос
/ 19 сентября 2012

Отмеченный как подход с ответом имеет один недостаток - содержимое TabItem всегда будет перерисовываться при выборе. Если это важно - вы можете попробовать это .

1 голос
/ 07 октября 2010

Я создал это решение, которое работает для нашего стороннего tabcontrol.

Идея состоит в том, чтобы «перехватить» текст данных, когда он задан, сохранить его на потом и вернуть ноль в текст данных. Когда табайт получает фокус, мы устанавливаем текстовый текст данных, и данные будут заполняться на вкладке.

Реализовано как свойство зависимости. Затем просто установите свойство на нужных вкладках (не устанавливайте его на вкладке, которая появляется по умолчанию)

    #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;
    }
...