【问题标题】:Change View on Button Click with MVVM (No code Behind) and without Navigation使用 MVVM(无代码)和无导航更改按钮单击的视图
【发布时间】:2016-09-02 16:49:47
【问题描述】:

我正在使用 WPF MVVM。

我有一个 WCF 聊天服务,它应该执行某些验证操作(用户凭据)以便向聊天窗口发送消息..

这当然发生在我按下按钮“登录!”的那一刻。

我想要完成的是在我按下登录并且验证成功的那一刻的新视图(聊天窗口视图)。

*由于我还没有聊天视图,假设我的聊天视图是我的注册视图(只是为了了解如何使用 ICommand 在按钮单击时切换视图)

我将发布我所做的:

MainWindow.xaml:

    <Window.Resources>
    <DataTemplate DataType="{x:Type  ViewModels:LoginViewModel}">
        <Views:LoginView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:SignUpViewModel}">
        <Views:SignUpView />
    </DataTemplate>
</Window.Resources>
<Grid>
    <ContentControl Content="{Binding CurrentView}" />
</Grid>

MainWindow.xaml.cs:

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new AppViewModel();
    }
}

LoginViewModel.cs

    public class LoginViewModel : ViewModelBase
{
    public AuthenticatedUser AuthenticatedUser { get; set; }
    private string username;

    public string UserName
    {
        get { return username; }
        set {
            username = value;
            Notify();
        }
    }
    private string password;
    public string Password
    {
        get { return password; }
        set
        {
            password = value;
            Notify();
        }
    }

    public ConsoleLog ConsoleLog { get ; set; } // TODO: StringBuilder.
    public UserServiceProxy UserServiceProxy { get; set; }
    public ChatServiceProxy ChatServiceProxy { get; set; }

    public LoginViewModel()
    {
        AuthenticatedUser = AuthenticatedUser.Instance;
        UserServiceProxy = new UserServiceProxy();
        ChatServiceProxy = new ChatServiceProxy();
        SendLoginRequestCommand = new MyCommand(SendLoginRequest);
        ConsoleLog = new ConsoleLog();
        ConsoleLog.Document = "Binding Checker.";
    }

    public ICommand SendLoginRequestCommand { get; set; }

    private void SendLoginRequest()
    {
      LoginResponse response = UserServiceProxy.Login(new LoginRequest { UserName = UserName, Password = Password });
        ConsoleLog.Document += $"{response.IsSuccess} {response.Message}";
      if(response.IsSuccess == true)
        {
            AuthenticatedUser.Authentication = response.Authentication;
            JoinServiceResponse responseFromChatService = ChatServiceProxy.JoinService(new JoinServiceRequest());
            ConsoleLog.Document += responseFromChatService.Message;

            /* This is where I think the view should be changed,yet no success for a few days now.
             * 
             * 
             * 
             * 
             * 
             */
        }

    }

    private void LoginEventRaised(object sender, OnLoginEventArgs e)
    {
        ConsoleLog.Document += $"{e.UserName} has logged in.";
    }
}

SignUpViewModel.cs:

    public class SignUpViewModel : ViewModelBase
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string PasswordConfirm { get; set; }
    public ConsoleLog ConsoleLog { get; set; }
    public UserServiceProxy UserServiceProxy { get; set; }

    public ICommand OnClickSignUpCommand { get; set; }

    public SignUpViewModel()
    {
        UserServiceProxy = new UserServiceProxy();
        ConsoleLog = new ConsoleLog { Document = "Check Register."};
        OnClickSignUpCommand = new MyCommand(SendSignUpRequest);
    }

    private void SendSignUpRequest()
    {
      SignUpResponse response = UserServiceProxy.SignUp(new SignUpRequest { UserName = UserName, Password = Password, PasswordConfirm = PasswordConfirm });
        if(response.IsSuccess == true)
        {
            ConsoleLog.Document += $"{response.IsSuccess} {response.Message}";
            response.AllOtherUsers.ForEach(u => ConsoleLog.Document += $"{u.UserName} Signed up.");
        }
    }
}

ViewModelBase.cs:

    public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void Notify([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

AppViewModel.cs:

    public class AppViewModel : ViewModelBase
{
    private ViewModelBase currentView;

    public ViewModelBase CurrentView
    {
        get { return currentView; }
        set {
            currentView = value;
            Notify();
        }
    }

    public ICommand ViewLoginCommand { get; }
    public ICommand ViewSignUpCommand { get; }

    public AppViewModel()
    {
        ViewLoginCommand = new MyCommand(SetCurrentViewToLoginViewModel);
        ViewSignUpCommand = new MyCommand(SetCurrentViewToSignUpViewModel);
        CurrentView = new LoginViewModel(); //temporary loading the first view the use will see.
    }
    private void SetCurrentViewToLoginViewModel()
    {
        CurrentView = new LoginViewModel();
    }
    public void SetCurrentViewToSignUpViewModel()
    {
        CurrentView = new SignUpViewModel();
    }
}

LoginView.xaml(这是一个用户控件):

    <Grid>
    <Button x:Name="login" Content="login" HorizontalAlignment="Left" Margin="292,171,0,0" VerticalAlignment="Top" Width="114" Height="33" Command="{Binding SendLoginRequestCommand}"/>
    <TextBox x:Name="passwordTextBox" HorizontalAlignment="Left" Height="34" Margin="292,103,0,0" TextWrapping="Wrap" Text="{Binding Password}" VerticalAlignment="Top" Width="141"/>
    <TextBox x:Name="userNameTextBox" HorizontalAlignment="Left" Height="34" Margin="292,51,0,0" TextWrapping="Wrap" Text="{Binding UserName}" VerticalAlignment="Top" Width="141"/>
    <TextBlock x:Name="consoleLog" HorizontalAlignment="Left" Margin="24,33,0,0" TextWrapping="Wrap" Text="{Binding Path = ConsoleLog.Document}" VerticalAlignment="Top" Height="232" Width="218" />
    <Button x:Name="logout" Content="logout" HorizontalAlignment="Left" Margin="292,232,0,0" VerticalAlignment="Top" Width="114" Height="33"/>
</Grid>

SignUpView.xaml(这个问题其实并不需要这段代码,但以防万一):

    <Grid>
    <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="30" Margin="310,24,0,0" TextWrapping="Wrap" Text="{Binding UserName}" VerticalAlignment="Top" Width="130"/>
    <TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="30" Margin="310,74,0,0" TextWrapping="Wrap" Text="{Binding Password}" VerticalAlignment="Top" Width="130"/>
    <TextBox x:Name="textBox2" HorizontalAlignment="Left" Height="30" Margin="310,124,0,0" TextWrapping="Wrap" Text="{Binding PasswordConfirm}" VerticalAlignment="Top" Width="130"/>
    <Button x:Name="register" Content="Register" HorizontalAlignment="Left" Margin="310,176,0,0" VerticalAlignment="Top" Width="130" Command="{Binding OnClickSignUpCommand}"/>
    <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="25,10,0,0" TextWrapping="Wrap" Text="{Binding  Path=ConsoleLog.Document}" VerticalAlignment="Top" Height="289" Width="253"/>
</Grid>

我知道我在这里遗漏了一些东西。可能是因为我尝试解决了几天的问题,所以我迷失了方向。

这是我的登录信息:(还不能嵌入)

LoginView.xaml

按下“登录”的那一刻,我需要加载下一个视图:

SignUpView.xaml

我不能为这个问题提供任何代表。不过,我非常感谢您的帮助。

浏览了网络,找不到合适的问题。

【问题讨论】:

    标签: c# wpf wcf xaml mvvm


    【解决方案1】:

    您确实在问题中提供了很多代码,请参阅Minimal, Complete, and Verifiable code example 在发布您的问题之前。

    如果我理解您在程序中尝试执行的操作,那么您的 AppViewModel 就是您的“MainNavigation”类,它负责管理所有视图并在它们之间导航。

    我可以为您提供的一个解决方案是向您的LoginViewModel 添加一个事件,该事件将在用户成功登录时引发。在您的AppViewModel 中,您将注册到此事件并实现一个处理程序,该处理程序会将CurrentView 属性更改为您的SignUpViewModel

    LoginViewModel.cs 的添加将如下所示:

    public class LoginViewModel : ViewModelBase
    {
        ...
    
        public delegate void UserLoginSuccessfullyHandler();
        public event UserLoginSuccessfullyHandler UserLoginSuccessfullyEvent;
    
        private void SendLoginRequest()
        {
          LoginResponse response = UserServiceProxy.Login(new LoginRequest { UserName = UserName, Password = Password });
            ConsoleLog.Document += $"{response.IsSuccess} {response.Message}";
          if(response.IsSuccess == true)
            {
                AuthenticatedUser.Authentication = response.Authentication;
                JoinServiceResponse responseFromChatService = ChatServiceProxy.JoinService(new JoinServiceRequest());
                ConsoleLog.Document += responseFromChatService.Message;
    
                // This is where you inform the AppViewModel to change his CurrentView
                if (UserLoginSuccessfullyEvent!= null)
                    UserLoginSuccessfullyEvent();
            }
        }
    
        ...
    }
    

    AppViewModel.cs 的添加将如下所示:

        public class AppViewModel : ViewModelBase
    {
        ...
    
        public AppViewModel()
        {
            var loginViewModel = new LoginViewModel();
            loginViewModel.UserLoginSuccessfullyEvent += new UserLoginSuccessfullyHandler(myUserLoginSuccessfullyHandler);
            CurrentView = loginViewModel;
        }
    
        private void myUserLoginSuccessfullyHandler()
        {
            CurrentView = new SignUpViewModel();
        }
    
        ...
    }
    

    您可以在此处查看有关活动的更多信息Events in C# .

    【讨论】:

      猜你喜欢
      • 2019-07-26
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多