第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

阻止TabControl重新創(chuàng)建其子級

阻止TabControl重新創(chuàng)建其子級

米脂 2019-12-25 10:49:08
我有一個IList綁定到的viewmodel TabControl。這IList不會在的使用期限內(nèi)發(fā)生變化TabControl。<TabControl ItemsSource="{Binding Tabs}" SelectedIndex="0" >    <TabControl.ItemContainerStyle>        <Style TargetType="TabItem">            <Setter Property="Content" Value="{Binding}" />        </Style>    </TabControl.ItemContainerStyle></TabControl>每個視圖模型都有一個DataTemplate在中指定的ResourceDictionary。<DataTemplate TargetType={x:Type vm:MyViewModel}>    <v:MyView/></DataTemplate>DataTemplate中指定的每個視圖都占用大量資源,以至于我寧愿只創(chuàng)建一次每個視圖,但是當我切換選項卡時,將調(diào)用相關視圖的構造函數(shù)。根據(jù)我的閱讀,這是的預期行為TabControl,但是對我來說,尚不清楚調(diào)用構造函數(shù)的機制是什么。我看過一個類似的問題,它使用了UserControls,但是那里提供的解決方案將需要我綁定到視圖,這是不希望的。
查看完整描述

3 回答

?
紅顏莎娜

TA貢獻1842條經(jīng)驗 獲得超13個贊

默認情況下,TabControl共享面板以呈現(xiàn)其內(nèi)容。若要做您想做的事情(以及許多其他WPF開發(fā)人員),您需要TabControl像這樣進行擴展:


TabControlEx.cs


[TemplatePart(Name = "PART_ItemsHolder", Type = typeof(Panel))]

public class TabControlEx : TabControl

{

    private Panel ItemsHolderPanel = null;


    public TabControlEx()

        : base()

    {

        // This is necessary so that we get the initial databound selected item

        ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;

    }


    /// <summary>

    /// If containers are done, generate the selected item

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)

    {

        if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

        {

            this.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;

            UpdateSelectedItem();

        }

    }


    /// <summary>

    /// Get the ItemsHolder and generate any children

    /// </summary>

    public override void OnApplyTemplate()

    {

        base.OnApplyTemplate();

        ItemsHolderPanel = GetTemplateChild("PART_ItemsHolder") as Panel;

        UpdateSelectedItem();

    }


    /// <summary>

    /// When the items change we remove any generated panel children and add any new ones as necessary

    /// </summary>

    /// <param name="e"></param>

    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

    {

        base.OnItemsChanged(e);


        if (ItemsHolderPanel == null)

            return;


        switch (e.Action)

        {

            case NotifyCollectionChangedAction.Reset:

                ItemsHolderPanel.Children.Clear();

                break;


            case NotifyCollectionChangedAction.Add:

            case NotifyCollectionChangedAction.Remove:

                if (e.OldItems != null)

                {

                    foreach (var item in e.OldItems)

                    {

                        ContentPresenter cp = FindChildContentPresenter(item);

                        if (cp != null)

                            ItemsHolderPanel.Children.Remove(cp);

                    }

                }


                // Don't do anything with new items because we don't want to

                // create visuals that aren't being shown


                UpdateSelectedItem();

                break;


            case NotifyCollectionChangedAction.Replace:

                throw new NotImplementedException("Replace not implemented yet");

        }

    }


    protected override void OnSelectionChanged(SelectionChangedEventArgs e)

    {

        base.OnSelectionChanged(e);

        UpdateSelectedItem();

    }


    private void UpdateSelectedItem()

    {

        if (ItemsHolderPanel == null)

            return;


        // Generate a ContentPresenter if necessary

        TabItem item = GetSelectedTabItem();

        if (item != null)

            CreateChildContentPresenter(item);


        // show the right child

        foreach (ContentPresenter child in ItemsHolderPanel.Children)

            child.Visibility = ((child.Tag as TabItem).IsSelected) ? Visibility.Visible : Visibility.Collapsed;

    }


    private ContentPresenter CreateChildContentPresenter(object item)

    {

        if (item == null)

            return null;


        ContentPresenter cp = FindChildContentPresenter(item);


        if (cp != null)

            return cp;


        // the actual child to be added.  cp.Tag is a reference to the TabItem

        cp = new ContentPresenter();

        cp.Content = (item is TabItem) ? (item as TabItem).Content : item;

        cp.ContentTemplate = this.SelectedContentTemplate;

        cp.ContentTemplateSelector = this.SelectedContentTemplateSelector;

        cp.ContentStringFormat = this.SelectedContentStringFormat;

        cp.Visibility = Visibility.Collapsed;

        cp.Tag = (item is TabItem) ? item : (this.ItemContainerGenerator.ContainerFromItem(item));

        ItemsHolderPanel.Children.Add(cp);

        return cp;

    }


    private ContentPresenter FindChildContentPresenter(object data)

    {

        if (data is TabItem)

            data = (data as TabItem).Content;


        if (data == null)

            return null;


        if (ItemsHolderPanel == null)

            return null;


        foreach (ContentPresenter cp in ItemsHolderPanel.Children)

        {

            if (cp.Content == data)

                return cp;

        }


        return null;

    }


    protected TabItem GetSelectedTabItem()

    {

        object selectedItem = base.SelectedItem;

        if (selectedItem == null)

            return null;


        TabItem item = selectedItem as TabItem;

        if (item == null)

            item = base.ItemContainerGenerator.ContainerFromIndex(base.SelectedIndex) as TabItem;


        return item;

    }

}

XAML


<Style TargetType="{x:Type controls:TabControlEx}">

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="{x:Type TabControl}">

                <Grid Background="{TemplateBinding Background}" ClipToBounds="True" KeyboardNavigation.TabNavigation="Local" SnapsToDevicePixels="True">

                    <Grid.ColumnDefinitions>

                        <ColumnDefinition x:Name="ColumnDefinition0" />

                        <ColumnDefinition x:Name="ColumnDefinition1" Width="0" />

                    </Grid.ColumnDefinitions>

                    <Grid.RowDefinitions>

                        <RowDefinition x:Name="RowDefinition0" Height="Auto" />

                        <RowDefinition x:Name="RowDefinition1" Height="*" />

                    </Grid.RowDefinitions>

                    <DockPanel Margin="2,2,0,0" LastChildFill="False">

                        <TabPanel x:Name="HeaderPanel" Margin="0,0,0,-1" VerticalAlignment="Bottom" Panel.ZIndex="1" DockPanel.Dock="Right"

                                  IsItemsHost="True" KeyboardNavigation.TabIndex="1" />

                    </DockPanel>

                    <Border x:Name="ContentPanel" Grid.Row="1" Grid.Column="0"

                            Background="{TemplateBinding Background}"

                            BorderBrush="{TemplateBinding BorderBrush}"

                            BorderThickness="{TemplateBinding BorderThickness}"

                            KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">

                        <Grid x:Name="PART_ItemsHolder" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />

                    </Border>

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>

注意:我沒有提出這個解決方案。它已在編程論壇中共享了數(shù)年,并且相信它現(xiàn)在已成為WPF食譜書之一。我認為最古老或原始的來源是PluralSight .NET博客文章,以及StackOverflow上的答案。


查看完整回答
反對 回復 2019-12-25
?
qq_花開花謝_0

TA貢獻1835條經(jīng)驗 獲得超7個贊

有一個不是很明顯但很優(yōu)雅的解決方案。主要思想是通過自定義轉(zhuǎn)換器手動生成TabItem的ContentTree的VisualTree屬性。


定義一些資源


<Window.Resources>

    <converters:ContentGeneratorConverter x:Key="ContentGeneratorConverter"/>


    <DataTemplate x:Key="ItemDataTemplate">

        <StackPanel>

            <TextBox Text="Try to change this text and choose another tab"/>

            <TextBlock Text="{Binding}"/>

        </StackPanel>

    </DataTemplate>


    <markup:Set x:Key="Items">

        <system:String>Red</system:String>

        <system:String>Green</system:String>

        <system:String>Blue</system:String>

    </markup:Set>

</Window.Resources>

哪里


public class ContentGeneratorConverter : IValueConverter

{

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

    {

        var control = new ContentControl {ContentTemplate = (DataTemplate) parameter};

        control.SetBinding(ContentControl.ContentProperty, new Binding());

        return control;

    }


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>

        throw new NotImplementedException();

}

Set是這樣的


public class Set : List<object> { }

然后改為經(jīng)典使用ContentTemplate屬性


    <TabControl

        ItemsSource="{StaticResource Items}"

        ContentTemplate="{StaticResource ItemDataTemplate}">

    </TabControl>

我們應該通過以下方式指定ItemContainerStyle


    <TabControl

        ItemsSource="{StaticResource Items}">

        <TabControl.ItemContainerStyle>

            <Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">

                <Setter Property="Content" Value="{Binding Converter={StaticResource ContentGeneratorConverter}, ConverterParameter={StaticResource ItemDataTemplate}}"/>

            </Style>

        </TabControl.ItemContainerStyle>

    </TabControl>

現(xiàn)在,嘗試比較兩種變體,以查看選項卡切換期間ItemDataTemplate處TextBox行為的不同。


查看完整回答
反對 回復 2019-12-25
  • 3 回答
  • 0 關注
  • 711 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號