Dynami c управляет переключением в WPF - PullRequest
0 голосов
/ 04 мая 2020

Название может вводить в заблуждение, но я не уверен, как его описать.

Допустим, у меня есть 2 контейнера - один слева, один справа. Левый контейнер имеет несколько кнопок. Нажатие на них изменит то, что внутри 2-го контейнера. Если я нажму 1-ю кнопку, появится набор кнопок и календарь, 2-я - datagridview et c. Его пример.

Как мне этого добиться? Я не прошу решения (оно не может быть решено в одной строке кода, очевидно), но что я должен искать. Какой-то конкретный c контроль? Отображение другого окна внутри него? Et c.

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Я не уверен, правильно ли я понял вопрос, поэтому я написал следующий сценарий из того, что я понял.

Как вы упомянули, у вас есть главное окно, которое содержит 2 панели, одну слева и другой справа. На левой панели есть список кнопок, размещенных в виде группы меню, которые при нажатии отображают другой контент на правой панели, что-то вроде перехода к другому системному модулю (см. Рисунок):

Demo

Если это ваш сценарий, вы можете спроектировать приложение WPF следующим образом:

  1. Создание пользовательских элементов управления для каждого экрана, к которому вы хотите перейти , В предыдущем примере вы могли создать UserControl для модуля списка задач и другой UserControl для модуля My Agenda. Проверьте эту ссылку, чтобы вы знали, что такое UserControl.
  2. Управление навигацией в главном окне. Как и в WinForms, вы можете обрабатывать событие click для каждой кнопки на левой панели, однако элегантный способ обработки события click заключается в том, что вы обрабатываете его в родительском контейнере, поскольку, в отличие от Winforms, событие click является пузырчатым. событие. Проверьте эту ссылку, чтобы вы знали, что такое маршрутизируемое событие и что является пузырящимся событием.
  3. В примере видео вы могли бы заметить, что каждый модуль находится в контейнере с заголовком и что текст заголовка изменяется при нажатии кнопки, а текст заголовка обновляется текстом кнопки? Это можно сделать разными способами, но хорошим способом сделать это является привязка данных, проверьте эту ссылку, чтобы понять, что это за концепция. Имея опыт, вы поймете, когда будет целесообразно применить это, а когда нет.

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

Я пишу пример кода, который я также публикую sh на GitHub . Я объясняю кое-что о коде, но предлагаю вам расширить эти понятия в ссылках, которые я оставил вам, и в других надежных источниках знаний, таких как книги или учебные пособия от самой Microsoft.

Главное окно Xaml:

<Window
    x:Class="WpfApp26.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:local="clr-namespace:WpfApp26"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800" Height="450"
    d:DataContext="{d:DesignInstance Type=local:ViewModel}"
    mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>

        <!--  A GroupBox is a control with a header  -->
        <GroupBox Header="Options">
            <!--  Look that the click event is handled in the StackPanel, the container for the buttons  -->
            <StackPanel Button.Click="ModuleSelected_OnClick">
                <Button
                    Margin="5" Padding="5"
                    Content="To Do List" Tag="ToDoListModule" />
                <Button
                    Margin="5" Padding="5"
                    Content="My Agenda" Tag="MyAgendaModule" />
            </StackPanel>
        </GroupBox>

        <!--  The header property is binding to the CurrentModuleName property in the DataContext  -->
        <GroupBox Name="GbCurrentModule" Grid.Column="1" Header="{Binding CurretModuleName}" />
    </Grid>
</Window>

Код MainWindow (см. INotifyProperyChanged ):

public partial class MainWindow : Window {
    private readonly ViewModel vm;

    public MainWindow() {
        InitializeComponent();

        // Setting the Window's DataContext to a object of the ViewModel class.
        this.DataContext = this.vm = new ViewModel();
    }

    private void ModuleSelected_OnClick(object sender, RoutedEventArgs e) {
        // The Source property of the RoutedEventArgs gets the Element that fires the event (in this case, the button).
        var clickedButton = (Button) e.Source;
        this.vm.CurretModuleName = clickedButton.Content.ToString();

        // Getting the Tag property of the button.
        var tag = clickedButton.Tag.ToString();

        // Performing the navigation.
        switch (tag) {
            case "ToDoListModule":
                NavigateToModule(new UcToDoListModule());
                break;
            case "MyAgendaModule":
                NavigateToModule(new UcMyAgendaModule());
                break;
        }

        #region Internal methods
        void NavigateToModule(UserControl uc) {
            this.GbCurrentModule.Content = uc;
        } 
        #endregion
    }
}

Класс ViewModel:

// The class implementents the INotifyPropertyChanged interface, that is used 
// by the WPF notifications system.
public class ViewModel : INotifyPropertyChanged {
    private string curretModuleName;
    public string CurretModuleName {
        get => this.curretModuleName;
        set {
            this.curretModuleName = value;
            this.OnPropertyChanged();
        }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    } 
    #endregion
}
0 голосов
/ 04 мая 2020

Вы можете использовать DataTemplates с привязкой данных: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview

Это позволит вам определять шаблоны, которые автоматически применяются к объектам указанных c типов. Таким образом, у вас может быть объект календаря, представление списка, сетка данных и т. Д. c, применяемые индивидуально.

Вы также можете использовать видимость, чтобы отображать / скрывать представление по своему желанию, когда нажимаются ваши кнопки.

Среды MVVM используют это довольно часто: https://compiledexperience.com/blog/posts/using-caliburn-micro-as-a-data-template-selector

Другой пример https://www.codemag.com/article/0907111/Dressing-Up-Your-Data-with-WPF-DataTemplates

Есть и другие MVVM Подходы, которые используют активаторы, чтобы показать / скрыть / сгенерировать новые объекты указанных c типов и отобразить их.

...