КонтентКонтроль Wpf

Новый вопрос программиста:

Я пытаюсь создать простую навигационную страницу приветствия, похожую на то, что вы видите на iPad.

У моего MainWindow есть заголовок (который не изменится), а остальное будет своего рода контейнером, который будет отображать разные вещи в зависимости от событий.

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

В настоящее время у меня есть страница приветствия как:

<UserControl x:Class="ContentControl.Views.WelcomeView"
         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:vm="clr-namespace:ContentControl.ViewModels"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <vm:WelcomeViewModel />
</UserControl.DataContext>
<Grid Background="red">
    <Grid.RowDefinitions >
        <RowDefinition Height="25*" />
        <RowDefinition Height="50*"/>
        <RowDefinition Height="25*"/>
    </Grid.RowDefinitions>

    <Rectangle Grid.Row="0" Fill="Green"/>
    <DockPanel Grid.Row="1" HorizontalAlignment="Center" Background="White">
        <Button Height="50" Width="50" Margin="5" Content="DASH" Command="{Binding ViewChangedCommand}" CommandParameter="Dashboard"/>
        <Button Height="50" Width="50" Margin="5" Content="ROOM" Command="{Binding ViewChangedCommand}" CommandParameter="MeetingRoom"/>
        <Button Height="50" Width="50" Margin="5" Content="SCREEN" Command="{Binding ViewChangedCommand}" CommandParameter="Screen" />
    </DockPanel>
    <Rectangle Grid.Row="2" Fill="Blue"/>
</Grid>
</UserControl>

ViewModel выглядит следующим образом:

class WelcomeViewModel : BaseViewModel
{
    private MainWindowViewModel _mainWindowVm;
    private RelayCommand<string> _viewChangedCommand;

    public ICommand ViewChangedCommand
    {
        get { return _viewChangedCommand ?? (_viewChangedCommand = new RelayCommand<string>(OnViewChanged)); }
    }


    public event EventHandler ViewChanged;

    private void OnViewChanged(string view)
    {
        EventHandler handler = ViewChanged;
        if (handler != null) handler(view, EventArgs.Empty);
    }

    public MainWindowViewModel MainWindowVm
    {
        get { return _mainWindowVm; }
        set
        {
            _mainWindowVm = value;
            OnPropertyChanged("MainViewModel");
        }
    }

    public WelcomeViewModel()
    {
        MainWindowVm = new MainWindowViewModel();
        ViewChanged += MainWindowVm.ViewChanged;
    }
}
}

И у меня есть главное окно следующим образом:

<Window x:Class="ContentControl.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:ContentControl.ViewModels"
    xmlns:views="clr-namespace:ContentControl.Views"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <vm:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
    <DataTemplate DataType="{x:Type vm:ScreenViewModel}">
        <views:ScreenView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:WelcomeViewModel}">
        <views:WelcomeView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:MeetingRoomViewModel}">
        <views:MeetingRoomView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:DashboardViewModel}">
        <views:DashboardView />
    </DataTemplate>
</Window.Resources>

<Grid>
    <StackPanel>
        <Label>This Is My Label</Label>
        <ContentControl x:Name="MainPanel" Content="{Binding Content, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
            MinHeight="200"
            MinWidth="200"
            HorizontalContentAlignment="Left" 
            VerticalContentAlignment="Center" 
            Focusable="False">
        </ContentControl>
    </StackPanel>
</Grid>
</Window>

Модель просмотра главного окна:

class MainWindowViewModel : BaseViewModel
{
    private UserControl _content;

    public UserControl Content
    {
        get { return _content; }
        set
        {
            _content = value;
            OnPropertyChanged("Content");
        }
    }



    public void ViewChanged(object o, EventArgs e)
    {
        switch (o.ToString())
        {
            case "Welcome":
                {
                    var welcome = new WelcomeView();
                   Content = welcome;
                    break;
                }
            case "MeetingRoom":
                {
                    var meetingRoom = new MeetingRoomView();
                    Content= meetingRoom;
                    break;
                }
            case "Dashboard":
                {
                    var dashboard = new DashboardView();
                    Content = dashboard;
                    break;
                }
            case "Screen":
                {
                    var screen = new ScreenView();
                    Content = screen;
                    break;
                }
        }

        MessageBox.Show(o.ToString());
    }

    public MainWindowViewModel()

    {

    }

}
}

Как мне подключить их для работы друг с другом? Итак, я могу показать WelcomeView как содержимое элемента управления контентом, а затем, когда я нажму кнопку, изменить ContentControl на то, что было выбрано.

Еще раз извините, я новичок в MVVM и WPF, и эти привязки путаются в моей голове.


person KitWat    schedule 21.09.2012    source источник


Ответы (1)


Кнопки DASH, ROOM, SCREEN должны быть в главном окне. ViewChangedCommand должен быть в MainWindowViewModel. И контент будет отображаться с помощью динамических шаблонов.

Если вам нужны кнопки на элементах управления: Итак, давайте поместим кнопки на элементы управления, но команда изменения содержимого должна быть в MainWindowViewModel. Чтобы сделать такую ​​привязку, вы должны сделать что-то вроде этого:

Command="{Binding Path=DataContext.ChangeContentCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

в твоих пуговицах

person Raúl Otaño    schedule 21.09.2012
comment
Я не хочу, чтобы они были в главном окне. Я хочу иметь возможность загружать элементы управления из каждого представления и использовать их в главном окне. Я не хочу, чтобы в главном окне были какие-либо кнопки. Кнопки только для представлений, загруженных из элемента управления контентом. - person KitWat; 21.09.2012
comment
Итак, давайте поместим кнопки на элементы управления, но команда изменения содержимого должна быть в MainWindowViewModel. Чтобы сделать такую ​​привязку, вы должны сделать что-то вроде этого - person Raúl Otaño; 21.09.2012
comment
Но я думаю, что это может иметь избыточный код. У вас могут быть кнопки блога в главном окне, а также элементы управления могут определять свои собственные кнопки. - person Raúl Otaño; 21.09.2012
comment
Извините, я новичок, это не имеет смысла, я не знаю, что вы просите меня изменить - person KitWat; 22.09.2012
comment
У вас есть ViewChangedCommand в вашем WelcomeViewModel, и он должен быть в вашей MainWindowViewModel, тогда кнопки в вашем элементе управления должны иметь привязку, как указано выше. Теперь ясно? Пожалуйста, скажите, если это не так. - person Raúl Otaño; 22.09.2012
comment
Он не может войти в модель представления MainWindow, или кнопки не будут вызывать его при выборе. - person KitWat; 22.09.2012
comment
Привязка, которую я написал, не работает? Вы установили MainWindow.DataContext = new MainWindowViewModel()? - person Raúl Otaño; 22.09.2012