WPF - 没有绑定时DataTemplate属性内的元素问题?

时间:2016-12-15 16:57:00

标签: c# wpf mvvm

我有以下TabControl:

<TabControl ItemsSource="{Binding Tabs"}>
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type vm:TabVM}">
            <TextBox></TextBox>
            <TextBox Text="{Binding SomeProperty}"></TextBox>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

意外行为是第一个TextBox在所有tabitems之间共享Text属性,而第二个TextBox有效地绑定到ViewModel属性。

我的需要是使第一个TextBox独立,即使没有绑定。

我该怎么办?

**更新**

经过多次尝试后,我决定使用 ikriv的TabContent.cs 。 我发现的唯一问题是调用 TabControl.Items.Refresh()(即删除tabItem后)会导致内部缓存重置。

一个不优雅但有效的解决方案可能是:

public ContentManager(TabControl tabControl, Decorator border)
{
    _tabControl = tabControl;
    _border = border;
    _tabControl.SelectionChanged += (sender, args) => { UpdateSelectedTab(); };

    /* CUSTOM */
    var view = CollectionViewSource.GetDefaultView(((TabControl)_tabControl).Items);
    view.CollectionChanged += View_CollectionChanged;
}

/*
 * This fix the internal cache content when calling items->Refresh() method
 * */
private void View_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.OldItems != null)
    {
        /* Retrieve all tabitems cache and store to a temp list */
        IList<ContentControl> cachedContents = new List<ContentControl>();

        foreach (var item in _tabControl.Items)
        {
            var tabItem = _tabControl.ItemContainerGenerator.ContainerFromItem(item);

            var cachedContent = TabContent.GetInternalCachedContent(tabItem);

            cachedContents.Add(cachedContent);
        }

        /* rebuild the view */
        _tabControl.Items.Refresh();

        /* Retrieve all cached content and store to the tabitems */
        int idx = 0;

        foreach (var item in _tabControl.Items)
        {
            var tabItem = _tabControl.ItemContainerGenerator.ContainerFromItem(item);

            TabContent.SetInternalCachedContent(tabItem, cachedContents[idx++]);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您应该使用数据绑定,因为相同的ContentTemplate将应用于ItemsSource中的所有项目。基本上切换标签时,只会刷新绑定。 TextBox不会重新创建也不会重置。

  

我该怎么办?

您可以通过处理TabControl的SelectionChanged事件并自己重置 TextBox控件来解决此问题:

private void tabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        TabControl tc = sender as TabControl;
        ContentPresenter cp = tc.Template.FindName("PART_SelectedContentHost", tc) as ContentPresenter;
        if(cp != null && VisualTreeHelper.GetChildrenCount(cp) > 0)
        {
            ContentPresenter cpp = VisualTreeHelper.GetChild(cp, 0) as ContentPresenter;
            if(cpp != null)
            {
                TextBox textBox = cpp.FindName("txt") as TextBox;
                if (textBox != null)
                    textBox.Text = string.Empty;
            }
        }
    }
    <TabControl x:Name="tabs" ItemsSource="{Binding Tabs}" SelectionChanged="tabs_SelectionChanged">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentPresenter>
                    <ContentPresenter.Content>
                        <StackPanel>
                            <TextBox x:Name="txt"></TextBox>
                        </StackPanel>
                    </ContentPresenter.Content>
                </ContentPresenter>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>

如果要在切换选项卡时将文本保留在TextBox中,可以使用以下文章中的附加行为并将其IsCached属性设置为true:https://www.codeproject.com/articles/460989/wpf-tabcontrol-turning-off-tab-virtualization

<TabControl ItemsSource="{Binding Items}" behaviors:TabContent.IsCached="True">
    <!-- Make sure that you don't set the TabControl's ContentTemplate property but the custom one here-->
    <behaviors:TabContent.Template>
        <DataTemplate>
            <StackPanel>
                <TextBox />
            </StackPanel>
        </DataTemplate>
    </behaviors:TabContent.Template>
</TabControl>

另一种方法是修改TabControl的ControlTemplate以包含一个ListBox,如#ge; gekka&#39;在MSDN论坛的以下主题中:https://social.msdn.microsoft.com/Forums/en-US/4b71a43a-26f5-4fef-8dc5-55409262298e/using-uielements-on-datatemplate?forum=wpf