0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34

MVVM WPF tab controls и tab content

12.06.2019, 08:26. Показов 4417. Ответов 25
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток, я относительно не давно вникаю в WPF и MVVM, принцип паттерна я вроде как понял и хотел попробовать что то смастерить, так вот нашел урок где реализуется таб контрол с контентом и решил повторить но что то наваял и не могу понять почему не работает) буду благодарен если помножите разобраться)))
Кликните здесь для просмотра всего текста

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
 
namespace mvvmTabControlApp.Commands
{
    class ActionCommand : ICommand
    {
        private readonly Action<object> action;
        private readonly Predicate<Object> predicate;
 
        public ActionCommand(Action<Object> action) : this(action, null)
        {
        }
 
        public ActionCommand(Action<Object> action, Predicate<Object> predicate)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action), @"You must specify an Action<T>.");
            }
 
            this.action = action;
            this.predicate = predicate;
        }
 
        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }
 
        public bool CanExecute(object parameter)
        {
            if (this.predicate == null)
            {
                return true;
            }
            return this.predicate(parameter);
        }
 
        public void Execute()
        {
            Execute(null);
        }
 
        public void Execute(object parameter)
        {
            this.action(parameter);
        }
    }
}

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace mvvmTabControlApp.Models
{
    public class DateTab : Tab
    {
        public DateTab()
        {
            Name = DateTime.Now.ToString();
        }
    }
}

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using mvvmTabControlApp.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
 
namespace mvvmTabControlApp.Models
{
    public interface ITab
    {
        string Name { get; set; }
        ICommand CloseCommand { get; }
        event EventHandler CloseRequested;
    }
 
    public abstract class Tab : ITab
    {
        public Tab()
        {
            CloseCommand = new ActionCommand(p => CloseRequested?.Invoke(this, EventArgs.Empty));
        }
        public string Name { get; set; }
        public ICommand CloseCommand { get; }
        public event EventHandler CloseRequested;
    }
}

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using mvvmTabControlApp.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using mvvmTabControlApp.Commands;
using System.Collections.Specialized;
 
namespace mvvmTabControlApp.ViewModels
{
    public class MainWindowViewModel
    {
        private readonly ObservableCollection<ITab> tabs;
        public MainWindowViewModel()
        {            
            NewTabCommand = new ActionCommand(p => NewTab());
            tabs = new ObservableCollection<ITab>();
            tabs.CollectionChanged += Tabs_CollectionChanged;
            Tabs = tabs;
        }
 
        public ICommand NewTabCommand { get; }
        public ICollection<ITab> Tabs { get; }
 
        private void NewTab()
        {
            Tabs.Add(new DateTab());
        }
 
        private void Tabs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            ITab tab;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    tab = (ITab)e.NewItems[0];
                    tab.CloseRequested += OnTabCloseRequested;
                    break;
                case NotifyCollectionChangedAction.Remove:
                    tab = (ITab)e.OldItems[0];
                    tab.CloseRequested += OnTabCloseRequested;
                    break;
            }
        }
 
        private void OnTabCloseRequested(object sender, EventArgs e)
        {
            Tabs.Remove((ITab)sender);
        }
    }
}

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Page x:Class="mvvmTabControlApp.Views.DateTabView"
      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:mvvmTabControlApp.Views"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="DateTabView">
 
    <Grid>
        <TextBlock Text="{Binding Name}"/>
    </Grid>
</Page>

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<Window x:Class="mvvmTabControlApp.Views.MainWindowView"
        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:mvvmTabControlApp"
        xmlns:tabs="clr-namespace:mvvmTabControlApp.Views"
        mc:Ignorable="d"
        Title="MainWindowView" Height="450" Width="800">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Command="{Binding NewTabCommand}" Margin="0,0,12,0">New Tab</Button>
        </StackPanel>
 
        <TabControl ItemsSource="{Binding Tabs}">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type tabs:DateTab}">
                    <tabs:DateTabView/>
                </DataTemplate>
            </TabControl.Resources>
 
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type mvvm:ITab}">
                    <TextBlock>
                        <Run Text="{Binding Name}"/>
                        <Hyperlink Command="{Binding CloseCommand}">X</Hyperlink>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
 
        </TabControl>
    </DockPanel>
</Window>


вот сам проект...
Кликните здесь для просмотра всего текста
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.06.2019, 08:26
Ответы с готовыми решениями:

Tab Control на WPF, переключение между вкладками по нажатию кнопки
Здравствуйте форумчане, есть вопрос связанный с Tab Control на WPF. Задача стоит следующая есть Tab Control с 5 вкладками. На каждой...

MVVM Button Content Properties работает не правильно
Всем привет. Задача очень простая, при нажатии на кнопку менять Content на другой кнопке, но это не происходит ViewModel ...

Как нажать alt+tab программно??
Нужно программно задать переключение между окнами (alt+ tab) подскажите пожалуйста. И как подключить функции winapi у меня приложение без...

25
 Аватар для imcavs™
-2 / 24 / 8
Регистрация: 19.02.2012
Сообщений: 438
12.06.2019, 21:19
Так если Вы по уроку делали, сделайте ещё раз согласно всем пунктам Вашего урока.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
12.06.2019, 21:28
HINCO, Вы, похоже, скопировали бездумно куски кода, а сами даже не знаете что такое пространства имён, контекст данных и т.д.
То есть у Вас нет даже самых начальных, базовых основ знаний.
Не торопитесь сразу хвататься за сложные элементы. Освойте сначала простое. Без этих базовых знаний невозможно освоить что-то более сложное.

Вашу View исправьте как показано ниже. Она начнёт работать, но в полной мере или нет я не знаю. Мне не понятно что Вы хотите от неё.

Разберитесь, поймите в чём ошибки, каких знаний Вам не хватает.
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<Window x:Class="mvvmTabControlApp.Views.MainWindowView"
        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:mvvmTabControlApp"
        xmlns:tabs="clr-namespace:mvvmTabControlApp.Views"
        xmlns:model="clr-namespace:mvvmTabControlApp.Models"
        xmlns:views="clr-namespace:mvvmTabControlApp.Views"
        xmlns:viewModel="clr-namespace:mvvmTabControlApp.ViewModels"
        mc:Ignorable="d"
        Title="MainWindowView" Height="450" Width="800">
    <Window.DataContext>
        <viewModel:MainWindowViewModel/>
    </Window.DataContext>
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Command="{Binding NewTabCommand}" Margin="0,0,12,0">New Tab</Button>
        </StackPanel>
 
        <TabControl ItemsSource="{Binding Tabs}">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type model:DateTab}">
                    <views:DateTabView/>
                </DataTemplate>
            </TabControl.Resources>
 
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type model:ITab}">
                    <TextBlock>
                        <Run Text="{Binding Name}"/>
                        <Hyperlink Command="{Binding CloseCommand}">X</Hyperlink>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
 
        </TabControl>
    </DockPanel>
</Window>
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
13.06.2019, 09:41  [ТС]
Всем спасибо, разобрался - всё заработало)
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<Window x:Class="mvvmTabControlApp.Views.MainWindowView"
        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:tabs="clr-namespace:mvvmTabControlApp.Views"
        mc:Ignorable="d"
        Title="MainWindowView" Height="450" Width="800">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Command="{Binding NewTabCommand}" Margin="0,0,0,0">New Tab</Button>
        </StackPanel>
 
        <TabControl ItemsSource="{Binding Tabs}">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type tabs:DateTabView}">
                    <tabs:DateTabView/>
                </DataTemplate>
            </TabControl.Resources>
 
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type tabs:DateTabView}">
                    <TextBlock>
                        <Run Text="{Binding Name}"/>
                        <Hyperlink Command="{Binding CloseCommand}">X</Hyperlink>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
 
        </TabControl>
    </DockPanel>
</Window>

вопрос правильно ли я указал
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        <TabControl ItemsSource="{Binding Tabs}">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type tabs:DateTabView}">
                    <tabs:DateTabView/>
                </DataTemplate>
            </TabControl.Resources>
 
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type tabs:DateTabView}">
                    <TextBlock>
                        <Run Text="{Binding Name}"/>
                        <Hyperlink Command="{Binding CloseCommand}">X</Hyperlink>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
или нет? или есть ещё какой вариант?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
13.06.2019, 10:39
Цитата Сообщение от HINCO Посмотреть сообщение
разобрался - всё заработало)
Если не трудно выложите рабочее решение - поможет кому-нибудь ещё.

Цитата Сообщение от HINCO Посмотреть сообщение
вопрос правильно ли я указал
DataType="{x:Type tabs:DateTabView}" вызывает большие сомнения.
По идее у Вас в Tabs типы с интерфейсом ITab из Model. А Вы прописываете шаблон для типа tabs:DateTabView, а это UC из View....
Непонятно даже, почему у Вас это заработало.
Надо увидеть полностью проект чтобы понять.
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
13.06.2019, 12:47  [ТС]
приложение запустилось но только контент в табах не работает, с вашими правками хмла и заменой DateTabView.xaml (Page) на DateTabView.xaml (UserControl) всё заработало
Кликните здесь для просмотра всего текста

Сам проект:
mvvmTabControlApp.rar
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
13.06.2019, 13:06
Цитата Сообщение от HINCO Посмотреть сообщение
только контент в табах не работает
Объясните, что за контент и как он должен работать.

Цитата Сообщение от HINCO Посмотреть сообщение
заменой DateTabView.xaml (Page) на DateTabView.xaml (UserControl) всё заработало
Page, насколько помню, должен быть вложен в Window. В другие элементы его вкладывать нельзя.
Так сейчас работает как Вам надо или что-то ещё не полностью работает?
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
13.06.2019, 16:53  [ТС]

по крайней мере выводит то что я хотел
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
15.06.2019, 07:39  [ТС]
столкнулся с трудностью добавление новых табов из проекта, я создал две кнопки "One Tab" и "Two Tab"

MainWindowView
Кликните здесь для просмотра всего текста

и два UserControl'a "OneTabView.xaml" и "TwoTabView.xaml" соответственно

OneTabView и TwoTabView
Кликните здесь для просмотра всего текста


подскажите как можно забиндить на кнопку свой UserControl что бы при нажатии на кнопку выдавал свой таб с именем кнопки которую нажал

Пример(Отфотошопил):
Кликните здесь для просмотра всего текста
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
15.06.2019, 08:32  [ТС]
разобрался - наверное не правильно сделал но это работает)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
15.06.2019, 11:37
Цитата Сообщение от HINCO Посмотреть сообщение
разобрался - наверное не правильно сделал но это работает)
Покажите как реализовали.

Добавлено через 2 минуты
Если у Вас если несколько типов UC которые должны выводится в зависимости от типа элемента коллекции Tabs - надо прописать несколько шаблонов данных. И в них привязать тип данных к типу UC.
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
16.06.2019, 09:15  [ТС]
Элд Хасп,
MainWindowViewModel.cs
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using mvvmTabControlApp.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using mvvmTabControlApp.Commands;
using System.Collections.Specialized;
 
namespace mvvmTabControlApp.ViewModels
{
    public class MainWindowViewModel
    {
        private readonly ObservableCollection<ITab> tabs;
        public MainWindowViewModel()
        {            
            //NewTabCommand = new ActionCommand(p => NewTab());
            NewTabCommand = new ActionCommand(p => NewDateTab());
            NewTabCommand1 = new ActionCommand(p => NewOneTab());
            NewTabCommand2 = new ActionCommand(p => NewTwoTab());
            tabs = new ObservableCollection<ITab>();
            tabs.CollectionChanged += Tabs_CollectionChanged;
            Tabs = tabs;
        }
 
        public ICommand NewTabCommand { get; }
        public ICommand NewTabCommand1 { get; }
        public ICommand NewTabCommand2 { get; }
        public ICollection<ITab> Tabs { get; }
 
        //private void NewTab()
        //{
        //    Tabs.Add(new DateTab());
        //}
 
        private void NewDateTab()
        {
            Tabs.Add(new DateTab());
        }
 
        private void NewOneTab()
        {
            Tabs.Add(new OneTab());
        }
 
        private void NewTwoTab()
        {
            Tabs.Add(new TwoTab());
        }
 
        private void Tabs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            ITab tab;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    tab = (ITab)e.NewItems[0];
                    tab.CloseRequested += OnTabCloseRequested;
                    break;
                case NotifyCollectionChangedAction.Remove:
                    tab = (ITab)e.OldItems[0];
                    tab.CloseRequested += OnTabCloseRequested;
                    break;
            }
        }
 
        private void OnTabCloseRequested(object sender, EventArgs e)
        {
            Tabs.Remove((ITab)sender);
        }
    }
}

MainWindowView.xaml
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button x:Name="DateTabButton" Command="{Binding NewTabCommand}" Margin="0,0,12,0">Date Tab</Button>
            <Button x:Name="OneTubButton" Command="{Binding NewTabCommand1}" Margin="0,0,12,0">One Tab</Button>
            <Button x:Name="TwoTubButton" Command="{Binding NewTabCommand2}" Margin="0,0,12,0">Two Tab</Button>
        </StackPanel>
 
        <TabControl ItemsSource="{Binding Tabs}" Margin="10" BorderBrush="Gainsboro">
            
            <TabControl.Resources>
 
                <Style TargetType="TabItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TabItem">
                                <Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Gainsboro" CornerRadius="0,0,0,0" Margin="2,0">
                                    <ContentPresenter x:Name="ContentSite"
                                        VerticalAlignment="Center"
                                        HorizontalAlignment="Center"
                                        ContentSource="Header"
                                        Margin="10,2"/>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="Border" Property="Background" Value="LightSkyBlue" />
                                    </Trigger>
                                    <Trigger Property="IsSelected" Value="False">
                                        <Setter TargetName="Border" Property="Background" Value="GhostWhite" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
 
                <DataTemplate DataType="{x:Type model:DateTab}">
                    <views:DateTabView/>
                </DataTemplate>
 
                <DataTemplate DataType="{x:Type model:OneTab}">
                    <views:OneTabView/>
                </DataTemplate>
 
                <DataTemplate DataType="{x:Type model:TwoTab}">
                    <views:TwoTabView/>
                </DataTemplate>
 
            </TabControl.Resources>
 
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type model:ITab}">
                    <TextBlock>                        
                        <Run Text="{Binding Name}"/>
                        <Hyperlink Command="{Binding CloseCommand}">X</Hyperlink>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
 
        </TabControl>

Обозреватель решений:
Кликните здесь для просмотра всего текста
Название: Screenshot_16.png
Просмотров: 159

Размер: 9.7 Кб
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
16.06.2019, 15:30
HINCO, несколько замечаний для практического применения.
  1. Не могу понять по выложенному коду. У Вас стиль <Style TargetType="TabItem"> работает? По идее, не должен. Если работает - скиньте архив проекта. Хочу посмотреть как он работает.

  2. У Вас в MainWindowViewModel три команды с одинаковым функционалом. Лучше объявите одну команду
    C#
    1
    
                NewTabCommand = new ActionCommand(p => NewTab(p));
    C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
            private void NewTab(object parameter)
            {
                if (parameter is Type type)
                {
                    if (type == typeof(DateTab))
                        Tabs.Add(new DateTab());
                    if (type == typeof(OneTab))
                        Tabs.Add(new OneTab());
                    if (type == typeof(TwoTab))
                        Tabs.Add(new TwoTab());
                }
            }
    Тогда в XAML объявление кнопок будет таким
    XML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
            <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
                <StackPanel.Resources>
                    <Style TargetType="Button">
                        <Setter Property="Command" Value="{Binding NewTabCommand}"/>
                        <Setter Property="Margin" Value="0,0,12,0"/>
                        <Setter Property="Content" Value="{Binding CommandParameter.Name, RelativeSource={RelativeSource Self}}"/>
                    </Style>
                </StackPanel.Resources>
                <Button CommandParameter="{x:Type viewModel:DateTab}"/>
                <Button CommandParameter="{x:Type viewModel:OneTab}"/>
                <Button CommandParameter="{x:Type viewModel:TwoTab}"/>
            </StackPanel>
  3. Для чего Вы объявили типы ITab, Tab, DateTab, OneTab, TwoTab? Их основное предназначение различное отображение данных в View. Но Модель ни как не связанна с View. Значит эти типы относятся к ViewModel, а не Модель. Перенесите их в соответствующую папку.

  4. Тип Tab нужен для привязок в View, значит у него должна быть реализация INPC.
    На основе класса OnPropertyChangedClass из темы Пример создания приложения для тестирования [WPF, Элд Хасп] можно объявить так public abstract class Tab : OnPropertyChangedClass, ITab.

  5. Несколько производных типов нужны для различного их отображения. Но чем-то же они должны отличаться друг от друга и от базового класса.
    Для демонстрации такой пример
    DateTab
    C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
        public class DateTab : Tab
        {
            static int countTab = 0;
            public string TypeTab => GetType().Name;
            /// <summary>Порядковый номер создания вкладки</summary>
            public int NumberTab { get; }
            /// <summary>Время создания вкладки</summary>
            public DateTime CreateTab { get; }
            public DateTab()
            {
                CreateTab = DateTime.Now;
                Name = CreateTab.ToString();
                NumberTab = countTab++;
            }
        }
    OneTab
    C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
        public class OneTab : DateTab
        {
            private TimeSpan _lifespan;
            private readonly DispatcherTimer timer = new DispatcherTimer();
     
            /// <summary>Текст для примера</summary>
            public string Text => "Это таб типа \"OneTab\"";
            /// <summary>Время существования Tab</summary>
            public TimeSpan Lifespan { get => _lifespan; private set { _lifespan = value; OnPropertyChanged(); } }
            public OneTab(int intervalMilliseconds)
            {
                Name = DateTime.Now.ToString();
                timer.Interval = TimeSpan.FromMilliseconds(intervalMilliseconds);
                timer.Tick += Timer_Tick;
                timer.Start();
            }
            public OneTab() : this(100) { }
     
            protected virtual void Timer_Tick(object sender, EventArgs e)
            {
                Lifespan = DateTime.Now - CreateTab;
            }
        }
    TwoTab
    C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
        public class TwoTab : OneTab
        {
            protected static readonly Random random = new Random();
            /// <summary>Список перебираемых цветов</summary>
            private static readonly PropertyInfo[] colors =
            {
                typeof(Brushes).GetProperty(nameof(Brushes.Aqua)),
                typeof(Brushes).GetProperty(nameof(Brushes.Red)),
                typeof(Brushes).GetProperty(nameof(Brushes.Green)),
                typeof(Brushes).GetProperty(nameof(Brushes.Yellow))
            };
     
            private Brush _colorCurrent;
            private string _nameColor;
            private int currSec = -1;
     
            /// <summary>Имя текущего цвета</summary>
            public Brush ColorCurrent { get => _colorCurrent; private set { _colorCurrent = value; OnPropertyChanged(); } }
            /// <summary>Кисть текущего цвета</summary>
            public string NameColor { get => _nameColor; private set { _nameColor = value; OnPropertyChanged(); } }
     
            protected override void Timer_Tick(object sender, EventArgs e)
            {
     
                base.Timer_Tick(sender, e);
                if (Lifespan.Seconds != currSec)
                {
                    currSec = Lifespan.Seconds;
                    int index;
                    while ((colors[index = random.Next(colors.Length)].Name) == NameColor) ;
                    NameColor = colors[index].Name;
                    ColorCurrent = (Brush)colors[index].GetValue(null);
                }
            }
        }
  6. Теперь для каждого типа данных можно объявить своё отображение. Причём в производном классе, если надо, можно использовать отображение базового.

    DateTabView
    XML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    <UserControl x:Class="mvvmTabControlApp.Views.DateTabView"
                 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:mvvmTabControlApp.Views"
                 xmlns:viewModel="clr-namespace:mvvmTabControlApp.ViewModels"
                 mc:Ignorable="d" d:DataContext="{x:Type viewModel:DateTab}"
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
            <StackPanel>
                <TextBlock Text="{Binding Name}"/>
                <TextBlock>
                    <Run Text="Номер создания вкладки"/>
                    <Run Text="{Binding NumberTab, Mode=OneWay}"/>
                </TextBlock>
                <TextBlock>
                    <Run Text="Время создания вкладки:"/>
                    <Run Text="{Binding CreateTab.Minute, Mode=OneWay}" />
                    <Run Text="минут"/>
                    <Run Text="{Binding CreateTab.Second, Mode=OneWay}"/>
                     <Run Text="секунд."/>
               </TextBlock>
            </StackPanel>
        </Grid>
    </UserControl>
    OneTabView
    XML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    <UserControl x:Class="mvvmTabControlApp.Views.OneTabView"
                 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:mvvmTabControlApp.Views"
                 xmlns:viewModel="clr-namespace:mvvmTabControlApp.ViewModels"
                 mc:Ignorable="d" d:DataContext="{x:Type viewModel:OneTab}"
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
            <StackPanel>
                <local:DateTabView/>
                <TextBlock>
                    <Run Text="Время жизни вкладки:"/>
                    <Run Text="{Binding Lifespan.Minutes, Mode=OneWay}"/>
                    <Run Text="минут"/>
                    <Run Text="{Binding Lifespan.Seconds, Mode=OneWay}"/>
                    <Run Text="секунд."/>
                </TextBlock>
            </StackPanel>
        </Grid>
    </UserControl>
    TwoTabView
    XML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    <UserControl x:Class="mvvmTabControlApp.Views.TwoTabView"
                 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:mvvmTabControlApp.Views"
                 xmlns:viewModel="clr-namespace:mvvmTabControlApp.ViewModels"
                 mc:Ignorable="d" d:DataContext="{x:Type viewModel:TwoTab}"
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
            <StackPanel>
                <local:OneTabView/>
                <TextBlock>
                    <Run Text="Цвет:"/>
                    <Run Text="{Binding NameColor, Mode=OneWay}"/>
                </TextBlock>
                <Border Margin="20" Width="100" Height="100" Background="{Binding ColorCurrent}"/>
            </StackPanel>
        </Grid>
    </UserControl>

Архив проекта с внесёнными изменениями прилагаю
Вложения
Тип файла: 7z mvvmTabControlApp.7z (178.9 Кб, 15 просмотров)
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
16.06.2019, 16:22  [ТС]
Элд Хасп, не чего не понял - но очень интересно, спасибо за подсказки) учебное приложение задали написать а в учебном заведении фиг чему научили хD выкручиваюсь как могу)
вот проект:
mvvmTabControlApp.rar
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
16.06.2019, 16:41
Цитата Сообщение от HINCO Посмотреть сообщение
не чего не понял - но очень интересно
Задавайте вопросы - отвечу. Может не быстро (зависит от свободного времени), но отвечу.

Добавлено через 4 минуты
Цитата Сообщение от HINCO Посмотреть сообщение
вот проект:
Ну, это проект уже без стиля <Style TargetType="TabItem">.
У меня именно он вызывал сомнения.

Добавлено через 2 минуты
Цитата Сообщение от HINCO Посмотреть сообщение
учебное приложение задали написать а в учебном заведении фиг чему научили хD выкручиваюсь как могу)
Ну, суть задания в чём?
Раз Вы создаёте различны типы Tab - значит есть какие-то различные типы данных для которых нужно различное отображение (Представление).
Что это за типы данных?
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
16.06.2019, 16:41  [ТС]
Элд Хасп, спасибо, я просто ещё до таких сложных конструкций в книге не дошел - думаю вопросы по мере изучения будут появляться)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
16.06.2019, 16:46
Цитата Сообщение от HINCO Посмотреть сообщение
я просто ещё до таких сложных конструкций в книге не дошел
Сложность кажущаяся.
Там всё очень просто.
Просто надо понимать что с чем и как связано.
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
16.06.2019, 19:13  [ТС]
Элд Хасп, по большей части разобрался, спасибо)
в UC через DataGrid вывел инфу о людях и упёрся - скролл не появляется при уменьшении окна (Вертикальный) а вот с горизонтальным всё в порядке 0о думал я в гридах что то напутал что он не подхватывает по вертикале но там всё в порядке...

Горизонтальный скролл появился при уменьшении окна с права налево
Кликните здесь для просмотра всего текста

Вертикальный скролл не появился при уменьшении с верху вниз
Кликните здесь для просмотра всего текста
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
15974 / 11107 / 2867
Регистрация: 21.04.2018
Сообщений: 32,650
Записей в блоге: 2
16.06.2019, 19:26
Цитата Сообщение от HINCO Посмотреть сообщение
в UC через DataGrid вывел инфу о людях и упёрся - скролл не появляется при уменьшении окна (Вертикальный)
HINCO, если задаёте вопрос, то скидывайте или код или лучше архив проекта.
Надо же запускать код и смотреть что не так. Просто по скинам ответить же невозможно.
0
0 / 0 / 0
Регистрация: 25.02.2018
Сообщений: 34
16.06.2019, 19:46  [ТС]
Элд Хасп, mvvmTabControlApp.rar
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.06.2019, 19:46
Помогаю со студенческими работами здесь

RadioPanelGroup.Controls в WPF
Подскажите пожалуйста, как получить перечисление эллементов StackPanel(например). На windows forms работало по такому принципу: ...

Есть ли аналог this.Controls из WinForms в WPF?
Для сохранения настроек своих программ использую перебор всех элементов и сохранение данных с элементов нужного типа, в WinForms было все...

WPF MVVM
Привет всем! Изучаю патерн MVVM. Не могу понять как реализовать ее, если допустим мне необходимо одно и тоже окно использовать для разных ...

[WPF] Изменение Content у Label в методе
Есть метод , который принимает данные по udp: static void UdpData(IAsyncResult result) { UdpClient...

Treeview в WPF и MVVM
Доброе утро! Подскажите плз, статьи, примеры проектов и что нибудь еще для повышения осознанности при работе с таким элементов как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Анализ и линтинг кода JavaScript: ESLint, Prettier и JSHint
run.dev 26.04.2025
JavaScript прошёл долгий путь от простого языка для анимации веб-страниц до основы современной веб-разработки. С ростом сложности приложений, увеличением кодовых баз и масштабированием команд. . .
Паттерны в Python: Singleton, Factory и Observer
py-thonny 26.04.2025
Паттерны проектирования — это проверенные временем решения типовых проблем разработки программного обеспечения. Их история берёт начало с книги "Приёмы объектно-ориентированного проектирования. . . .
Исключения в C#: Stack Overflow, Access Violation и Out of memory
stackOverflow 26.04.2025
Исключения в C# — это не только механизм оповещения о проблемах, а целое искусство управления потоком выполнения программы в экстремальных ситуациях. Обычное исключение, например,. . .
Логирование в C# ASP.NET Core с помощью Serilog, ElasticSearch, Kibana
stackOverflow 25.04.2025
Помните те времена, когда для анализа проблемы приходилось подключаться к серверу, искать нужный лог-файл среди десятков других и вручную фильтровать тысячи строк в поисках ошибки? К счастью, эти дни. . .
Структура "железный OnKeyUp" вместо антидребезга. Полностью асинхронный счётчик.
Hrethgir 25.04.2025
Программа для симуляции схемы - Logisim Evolution В общем какое-то время отвлёкся, так было надо, теперь когда запилю это на verilog и FPGA , досоставлю заявку в ФИПС на полезную модель - не готов. . .
Автоматизация Amazon Web Services (AWS) с Boto3 в Python
py-thonny 25.04.2025
Облачные вычисления стали неотъемлемой частью современной ИТ-инфраструктуры, а Amazon Web Services (AWS) занимает лидирующие позиции среди провайдеров облачных услуг. Управление многочисленными. . .
Apache Kafka vs RabbitMQ в микросервисной архитектуре
ArchitectMsa 25.04.2025
Современная разработка ПО всё чаще склоняется к микросервисной архитектуре — подходу, при котором приложение разбивается на множество небольших, автономных сервисов. В этой распределённой среде. . .
Параллельное программирование с OpenMP в C++
NullReferenced 24.04.2025
Параллельное программирование — подход к созданию программ, когда одна задача разбивается на несколько подзадач, которые могут выполняться одновременно. Оно стало необходимым навыком для. . .
Цепочки методов в C# с Fluent API
UnmanagedCoder 24.04.2025
Современное программирование — это не только решение функциональных задач, но и создание кода, который удобно поддерживать, расширять и читать. Цепочки методов и Fluent-синтаксис в C# стали мощным. . .
Мульти-тенантные БД с PostgreSQL Row Security
Codd 23.04.2025
Современные облачные сервисы и бизнес-приложения всё чаще обслуживают множество клиентов в рамках единой программной инфраструктуры. Эта архитектурная модель, известная как мульти-тенантность, стала. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru