2

Может кто то с таким сталкивался или понимает в чем дело.

Элемент card, состоит из TabControl с двумя TabItem, во втором TabItem TabControl'а, должен быть общий UserControl, его выразил через static.

при переходе с одного card на другой, получается, что общий UserControl не отображается, отобразится в том случае когда происходит переключение между TabItem текущего Card.

Записал видео

MainWindow.xaml

<Window x:Class="StaticUC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:StaticUC"
        xmlns:card="clr-namespace:StaticUC.UC"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TreeView Grid.Column="0" x:Name="TreeV">
            <TreeViewItem Header="Card_1" Selected="Card_1_Selected"/>
            <TreeViewItem Header="Card_2" Selected="Card_2_Selected"/>
        </TreeView>
    &lt;Grid Grid.Column=&quot;1&quot; x:Name=&quot;MainGrid&quot;&gt;
        &lt;card:Card x:Name=&quot;card1&quot;/&gt;
        &lt;card:Card x:Name=&quot;card2&quot;/&gt;
    &lt;/Grid&gt; 

&lt;/Grid&gt;

</Window>

События

private void Card_1_Selected(object sender, RoutedEventArgs e)
        {
            this.card1.Visibility = Visibility.Visible;
            this.card2.Visibility = Visibility.Hidden;
        }

private void Card_2_Selected(object sender, RoutedEventArgs e) { this.card1.Visibility = Visibility.Hidden; this.card2.Visibility = Visibility.Visible; }

card.xaml

<UserControl x:Class="StaticUC.UC.Card"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:StaticUC.UC"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TabControl>
            <TabItem Header="First"/>
            <TabItem Header="ForStaticUC" x:Name="TabForStatic"/>
        </TabControl>
    </Grid>
</UserControl>

card.cs

public partial class Card : UserControl
    {
        public Card()
        {
            InitializeComponent();
        this.TabForStatic.Content = TestUCStatic;
    }

    public static readonly TestUC TestUCStatic = new TestUC();
}

TestUC.xaml

<UserControl x:Class="StaticUC.UC.TestUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:StaticUC.UC"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="StaticUC" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40"/>
    </Grid>
</UserControl 
  • Есть такая вещь, зовется "привязками", настоятельно советую вам ее познать, ибо сейчас вы делаете все весьма странно... – EvgeniyZ Apr 11 '21 at 09:43
  • 1
    Здесь 2 замечания: 1) использовать статику для таких задач странно. Поизучайте суперпростой шаблон проектирования Singleton 2) вью-компоненты (контролы) не могут быть ни статичными, не синглтонами, это чревато багами при рендере интерфейса, поизучайте шаблон проектирования MVVM. Как разберетесь, поймете, что вьюмодель можно сделать синглтоном, а все контролы, которые будут к ней привязаны, будут выглядеть идентично, то есть как один и тот же контрол. Так что нажмите себе на "стоп" и покопайтесь в том, о чем я написал. Бесполезно точно не будет. – aepot Apr 11 '21 at 09:45
  • @EvgeniyZ, хотел уточнить, почему странно? на сколько знаю, одна из опций статики сделать какие то данные общими для всех экземпляров данного класса. И хотелось понять природу такого поведения пользовательского интерфейса – WarpGunOff Apr 11 '21 at 13:50
  • 1
    @WarpGunOff Я ругаюсь не на статику (хотя она тут тоже весьма странна и бесмысленна), я ругаюсь на ваш подход проектирования. Сейчас у вас контролы, это некий источник данных, допустим захотите вывести человек поле для ввода. вы напишете <TextBox Name="tb1"/>, а в коде, чтоб получить из него данные, вы будете писать tb1.Text, то есть, ваш контрол содержит в себе данные, необходимые для работы вашего проекта, что не есть хорошо. Правильным подходом будет отделение UI от логики, чтобы это был совершенно отдельный, независимый слой, тогда тот же пример будет таким: – EvgeniyZ Apr 11 '21 at 13:59
  • 1
    @WarpGunOff <TextBox Text="{Binding Text}"/>, заметьте, тут некое абстрактное значение Text, которого может и не быть, UI не знает что-либо про код. А в коде уже, вы можете для этого сделать одно простое свойство public string Text { get; set; }, которое уже и будет содержать в себе нужные данные, не храня их в контроле (UI). И тут как бы уже сами думаю заметили, что идет работа с простыми классами, а не дергание фиг пойми чего из UI. – EvgeniyZ Apr 11 '21 at 14:02
  • @WarpGunOff Также помните про правила проектирования, по которым вы можете понять сразу, что если у вас в коде что-либо дублируется, то вы явно делаете что-то не так, а у вас вон, this.card1.Visibility постоянно дублируется, когда это вовсе должно быть в триггерах XAML... Вон я делал TabControl с динамичными вкладками и контентом в них, поглядите если интересно, сразу поймете думаю, что ваш код явно не по тому пути идет. – EvgeniyZ Apr 11 '21 at 14:06
  • @EvgeniyZ, а вы про привязку говорите, я знаю что использование подобного "this.card1.Visibility" и "" это не хорошо, это я сделал так чтобы быстро собрать пример для моего главного вопроса. почему статический член помещенный во вкладки разных экземпляров одного класса, так себя ведет. хотел вот утончить, известны ли кому нибудь, причины такого поведения. – WarpGunOff Apr 11 '21 at 14:22

1 Answers1

3

Смотрите.

Вы не можете использовать один и тот же контрол одновременно в разных местах. Дело в том, что WPF-овские контролы рассчитаны на наличие лишь одного родительского элемента (например, у него есть ссылка на родительский элемент), и когда элемент по вашему замыслу принадлежит одновременно двум родителям, по крайней мере у одного из родителей (а то и у всех) работает неправильно.

Не делайте так. Если вам нужен «одинаковый» контрол, сделайте два отдельных экземпляра контрола. Если вам нужны разделяемые между экземплярами данные, привязывайтесь (DataContext, вот это всё) к одному и тому же экземпляру данных.

Не экономьте на контролах, это не окупится.


Почему сделано так, что контрол невозможно использовать в нескольких местах одновременно? Дело в том, что контролы наследуют от родительских контролов очень многое: значения наследуемых свойств, ресурсы, да и при вычислении размера происходит завязка на размеры родителя. Поэтому контрол знает своё место в визуальном дереве и активно использует его.

Не пытайтесь обмануть систему, дружите с ней. Или пытайтесь, но тогда вы должны очень хорошо понимать, что делаете.

VladD
  • 206,799