C # wpf привязка tabcontrol на основе выбора списка элементов - PullRequest
1 голос
/ 27 апреля 2019

Я хочу изменить полный TabControl на основе выбора ListItem. Итак, я создаю словарь с ключом (элемент списка) и значением (TabControl) в цикле. Каждый TabControl содержит 10 TabItems.

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ListboxContainer listBoxContainer = new ListboxContainer();
        TabControlContainer tabControlContainer = new TabControlContainer();

        Dictionary<string, TabControl> tabControlDict = new Dictionary<string, TabControl>();

        public MainWindow()
        {
            InitializeComponent();

            listBoxContainer.ListBoxItems = new string[] { "TabControl1", "TabControl2", "TabControl3" };

            DataContext = listBoxContainer;

            // Generate tabcontrols per listbox item
            foreach (var key in listBoxContainer.ListBoxItems)
            {
                TabControl tabControl = new TabControl();
                TabItem tabItem = new TabItem();

                for (int i = 0; i < 10; i++)
                {
                    tabItem.Header = $"Header: {i}";
                }

                tabControl.Items.Add(tabItem);

                tabControlDict.Add(key, tabControl);
            }

            tabControlContainer.TabControls = tabControlDict.Values.ToArray();


        }

    }

    public class TabControlContainer : INotifyPropertyChanged
    {
        private TabControl[] _tabControls;

        public TabControl[] TabControls
        {
            get => _tabControls;
            set
            {
                if (value != _tabControls)
                {
                    _tabControls = value;
                    NotifyPropertyChanged("TabControls");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class ListboxContainer : INotifyPropertyChanged
    {
        private string[] _listBoxitems;

        public string[] ListBoxItems
        {
            get => _listBoxitems;
            set
            {
                if (value != _listBoxitems)
                {
                    _listBoxitems = value;
                    NotifyPropertyChanged("ListBoxItems");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Я пытался привязать панель стека к tabcontrols, но не могу заставить ее работать.

Вот код MainWindow.xaml .

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel>
        <ListBox x:Name="Listbox" ItemsSource="{Binding ListBoxItems}"/>
        <StackPanel x:Name="TabControlContainer">
            <ItemsControl ItemsSource="{Binding TabControls}">
                <!--<ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>-->
            </ItemsControl>
        </StackPanel>
    </DockPanel>
</Window>

Итак, я хочу получить представление Master / Detail, где Master - это список, а Detail - его TabControl.

Я знаю, что могу вручную добавлять / удалять дочерние элементы Stackpanel, основываясь на выборе элементов списка, но мне кажется, что это не MVVM-способ.

1 Ответ

1 голос
/ 27 апреля 2019

Вы хотите ListBox и TabControl.

У обоих элементов управления есть элементы управления.

Они оба наследуются от Selector, поэтому у них есть SelectedItem.

Свяжите коллекцию моделей представления с вашим списком, назовите их чем-то значимым. PersonViewModel или FruitViewModel или что-то. Не называйте их listboxitem или чем-то с тем же именем или чем-то вроде имени элемента управления UI. По одному в ряду. Но давайте назовем их RowVM, как в модели представления, содержащей данные для строки списка.

Если вы связываетесь с SelectedItem этого ListBox, вы получаете экземпляр RowVM.

Вы можете связать это из вашего списка со свойством в WindowViewModel. Вы также можете привязать это свойство к другому элементу управления.

Вернемся к значимым именам.

Может быть, у Человека есть Обувь. Коллекция обуви, которую вы собираетесь показать в этом таб-контроле. Выберите человека в списке, и вы увидите его обувь на вкладке управления. Таким образом, PersonViewModel будет иметь наблюдаемую коллекцию обуви.

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

Если вы привяжете этот список к представлению коллекции, вы также можете использовать текущий элемент / запись в привязке.

https://social.technet.microsoft.com/wiki/contents/articles/29859.wpf-tips-bind-to-current-item-of-collection.aspx

И, конечно, это просто даст вам имя типа, потому что он не знает, как отобразить обувь. Но это не проблема, потому что у wpf есть целая система шаблонов данных. Это позволяет вам использовать шаблон для обуви.

Вы должны уметь гуглить примеры всего этого, но вот один из них на вкладке управления, а именно:

Как связать TabControl с коллекцией ViewModels?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...