第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

MVVM 視圖之間切換

MVVM 視圖之間切換

PHP
BIG陽(yáng) 2024-01-20 15:55:21
我是 WPF 新手,請(qǐng)耐心等待。我有一個(gè) WinForms 應(yīng)用程序,我正在嘗試在 WPF 中重做。在我當(dāng)前的 WinForms 應(yīng)用程序中,我將所有控件粘貼到一個(gè)窗體中,并根據(jù)點(diǎn)擊的按鈕隱藏/顯示它們,以及使用第二個(gè)窗體。我的目標(biāo):創(chuàng)建不同的視圖,以便根據(jù)按下的按鈕在不同的視圖之間平滑切換,而不是隱藏控件或制作單獨(dú)的表單,然后隱藏它們。我當(dāng)前有一個(gè) MainWindow 視圖(我的初始啟動(dòng)窗口),通過(guò)一個(gè)按鈕,我可以切換到 CreateAccount 視圖。我遇到的問(wèn)題是,如何使 CreateAccount 中的按鈕“返回”主窗口?我的最終目標(biāo)是能夠根據(jù)按鈕點(diǎn)擊在 4 個(gè)視圖之間切換。這是我的 MainWindow.xaml<Window x:Class="MusicPlayer.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:MusicPlayer"        xmlns:Views="clr-namespace:MusicPlayer.Views"        xmlns:ViewModels="clr-namespace:MusicPlayer.ViewModels"        Title="MainWindow" Height="450" Width="800">    <Window.Resources>        <DataTemplate x:Name="CreateAccountTemplate" DataType="{x:Type ViewModels:CreateAccountViewModel}">            <Views:CreateAccountView DataContext="{Binding}"/>        </DataTemplate>    </Window.Resources>    <Grid>        <Button x:Name="TestButton" Content="Button" HorizontalAlignment="Left" Margin="164,182,0,0" VerticalAlignment="Top" Height="61" Width="68" Click="CreateAccountView_Clicked"/>        <PasswordBox HorizontalAlignment="Left" Margin="164,284,0,0" VerticalAlignment="Top" Width="120"/>        <ContentPresenter Content="{Binding}"/>    </Grid></Window>我的 MainWindow.xaml.csusing System;using System.Windows;using MusicPlayer.ViewModels;namespace MusicPlayer {    public partial class MainWindow : Window {        public MainWindow() {            InitializeComponent();        }
查看完整描述

1 回答

?
九州編程

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超4個(gè)贊

在我看來(lái),你目前的嘗試是在正確的軌道上。您發(fā)布的代碼的主要問(wèn)題是CreateAccountView.Button_Click()處理程序無(wú)權(quán)訪問(wèn)DataContext它應(yīng)該設(shè)置的屬性:

private void Button_Click(object sender, RoutedEventArgs e) {
    DataContext = new MainWindowViewModel();
}

DataContext屬性屬于CreateAccountView用戶控件。但是,這不是所顯示內(nèi)容的控制上下文。因此更改該屬性的值DataContext不會(huì)產(chǎn)生任何有用的效果。(事實(shí)上,用戶控件DataContext根本不應(yīng)該設(shè)置自己的屬性,因?yàn)檫@樣做會(huì)丟棄使用該用戶控件的客戶端代碼設(shè)置的任何上下文。)

沒(méi)有足夠的上下文來(lái)確切地知道執(zhí)行此操作的最佳方法是什么。我認(rèn)為在 Stack Overflow 上不可能提供足夠的上下文。整體架構(gòu)將取決于程序的太多小細(xì)節(jié)。但是,我認(rèn)為解決這個(gè)問(wèn)題的一種很好的方法是:

  • 創(chuàng)建一個(gè)“主”視圖模型來(lái)管理應(yīng)用程序的整體行為

  • 創(chuàng)建與 UI 的不同狀態(tài)相關(guān)的單獨(dú)視圖模型

  • 讓主視圖模型配置各個(gè)視圖模型,根據(jù)用戶輸入(例如單擊按鈕)適當(dāng)切換當(dāng)前視圖模型

將其翻譯成代碼,看起來(lái)像這樣......

首先,視圖模型:

class MainViewModel : NotifyPropertyChangedBase

{

    private object _currentViewModel;

    public object CurrentViewModel

    {

        get => _currentViewModel;

        set => _UpdateField(ref _currentViewModel, value);

    }


    private readonly HomeViewModel _homeViewModel;

    private readonly Sub1ViewModel _sub1ViewModel;

    private readonly Sub2ViewModel _sub2ViewModel;


    public MainViewModel()

    {

        _sub1ViewModel = new Sub1ViewModel

        {

            BackCommand = new DelegateCommand(() => CurrentViewModel = _homeViewModel)

        };


        _sub2ViewModel = new Sub2ViewModel

        {

            BackCommand = new DelegateCommand(() => CurrentViewModel = _homeViewModel)

        };


        _homeViewModel = new HomeViewModel

        {

            ShowSub1Command = new DelegateCommand(() => CurrentViewModel = _sub1ViewModel),

            ShowSub2Command = new DelegateCommand(() => CurrentViewModel = _sub2ViewModel)

        };


        CurrentViewModel = _homeViewModel;

    }

}


class HomeViewModel : NotifyPropertyChangedBase

{

    private ICommand _showSub1Command;

    public ICommand ShowSub1Command

    {

        get => _showSub1Command;

        set => _UpdateField(ref _showSub1Command, value);

    }


    private ICommand _showSub2Command;

    public ICommand ShowSub2Command

    {

        get => _showSub2Command;

        set => _UpdateField(ref _showSub2Command, value);

    }

}


class Sub1ViewModel : NotifyPropertyChangedBase

{

    private ICommand _backCommand;

    public ICommand BackCommand

    {

        get => _backCommand;

        set => _UpdateField(ref _backCommand, value);

    }

}


class Sub2ViewModel : NotifyPropertyChangedBase

{

    private ICommand _backCommand;

    public ICommand BackCommand

    {

        get => _backCommand;

        set => _UpdateField(ref _backCommand, value);

    }

}

當(dāng)然,這些視圖模型只包含處理 UI 切換所需的實(shí)現(xiàn)細(xì)節(jié)。在您的程序中,每個(gè)視圖狀態(tài)還包含您需要的特定于每個(gè)視圖狀態(tài)的內(nèi)容。


在我的小示例中,“主頁(yè)”視圖包含幾個(gè)按鈕,用于選擇可用的各個(gè)子視圖:


<UserControl x:Class="WpfApp1.HomeView"

             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" 

             mc:Ignorable="d" 

             d:DesignHeight="450" d:DesignWidth="800">

  <StackPanel Orientation="Horizontal">

    <TextBlock Text="Home: "/>

    <Button Content="Sub1" Command="{Binding ShowSub1Command}"/>

    <Button Content="Sub2" Command="{Binding ShowSub2Command}"/>

  </StackPanel>

</UserControl>

子視圖僅包含返回主視圖所需的按鈕:


<UserControl x:Class="WpfApp1.Sub1View"

             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" 

             mc:Ignorable="d" 

             d:DesignHeight="450" d:DesignWidth="800">

  <StackPanel Orientation="Horizontal">

    <TextBlock Text="Sub1 View: "/>

    <Button Content="Back" Command="{Binding BackCommand}"/>

  </StackPanel>

</UserControl>


<UserControl x:Class="WpfApp1.Sub2View"

             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" 

             mc:Ignorable="d" 

             d:DesignHeight="450" d:DesignWidth="800">

  <StackPanel Orientation="Horizontal">

    <TextBlock Text="Sub2 View: "/>

    <Button Content="Back" Command="{Binding BackCommand}"/>

  </StackPanel>

</UserControl>

最后,主窗口設(shè)置主視圖模型,并聲明用于每個(gè)特定子視圖的模板:


<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:l="clr-namespace:WpfApp1"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800">

  <Window.DataContext>

    <l:MainViewModel/>

  </Window.DataContext>

  <Window.Resources>

    <DataTemplate DataType="{x:Type l:HomeViewModel}">

      <l:HomeView/>

    </DataTemplate>

    <DataTemplate DataType="{x:Type l:Sub1ViewModel}">

      <l:Sub1View/>

    </DataTemplate>

    <DataTemplate DataType="{x:Type l:Sub2ViewModel}">

      <l:Sub2View/>

    </DataTemplate>

  </Window.Resources>

  <StackPanel>

    <ContentControl Content="{Binding CurrentViewModel}"/>

  </StackPanel>

</Window>

重要的是,您將看到所有視圖對(duì)象都不包含任何隱藏代碼。當(dāng)您以這種方式處理問(wèn)題時(shí),沒(méi)有必要這樣做,至少不是為了控制代碼中的基本行為。(您可能仍然會(huì)遇到視圖對(duì)象的代碼隱藏,但這通常只是為了實(shí)現(xiàn)該視圖對(duì)象特有的特定用戶界面行為,而不是為了處理視圖模型狀態(tài)。)


使用這種方法,您可以讓 WPF 完成盡可能多的繁重工作。它還將所有視圖模型對(duì)象相互解耦。有一個(gè)清晰的層次結(jié)構(gòu):只有頂級(jí)“主”視圖模型才知道其他視圖模型。這允許子視圖模型(“home”、“sub1”和“sub2”)根據(jù)需要在其他場(chǎng)景中重用,而無(wú)需在其中進(jìn)行任何修改或特殊情況處理。



這是我上面使用的輔助類(lèi):


class NotifyPropertyChangedBase : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;


    protected void _UpdateField<T>(ref T field, T newValue,

        Action<T> onChangedCallback = null,

        [CallerMemberName] string propertyName = null)

    {

        if (EqualityComparer<T>.Default.Equals(field, newValue))

        {

            return;

        }


        T oldValue = field;


        field = newValue;

        onChangedCallback?.Invoke(oldValue);

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }

}

class DelegateCommand : ICommand

{

    private readonly Action _execute;


    public DelegateCommand(Action execute)

    {

        _execute = execute;

    }


#pragma warning disable 67

    public event EventHandler CanExecuteChanged;

#pragma warning restore


    public bool CanExecute(object parameter) => true;


    public void Execute(object parameter) => _execute();

}


查看完整回答
反對(duì) 回復(fù) 2024-01-20
  • 1 回答
  • 0 關(guān)注
  • 172 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)