【问题标题】:Should these members be in a model? and if so, how?这些成员应该在模型中吗?如果是这样,如何?
【发布时间】:2019-03-04 09:44:03
【问题描述】:

我是 WPF 和 Prism 的新手,所以,我目前正试图弄清楚一些非常基本的事情。我的小实验运行时是这样的:

我有一个Views\Registration.xaml,看起来像这样:

<UserControl x:Class="Configurator.Views.Registration"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Label Grid.Column="0" Grid.Row="0" Content="Email:" HorizontalContentAlignment="Right" Margin="6"/>
        <TextBox Grid.Column="1" Grid.Row="0" x:Name="email" Margin="6" Text="{Binding Email}"/>
        <Label Grid.Column="0" Grid.Row="1" Content="Password:" HorizontalContentAlignment="Right" Margin="6"/>
        <PasswordBox Grid.Column="1" Grid.Row="1" x:Name="password" Margin="6" />
        <Label Grid.Column="0" Grid.Row="2" Content="Password Confirmation:" HorizontalContentAlignment="Right" Margin="6"/>
        <PasswordBox Grid.Column="1" Grid.Row="2" x:Name="passwordConfirmation" Margin="6"/>
        <Button Grid.Column="1" Grid.Row="3" Content="Register" HorizontalAlignment="Left" Margin="6" Padding="6,2" Command="{Binding RegisterCommand}"/>
    </Grid>
</UserControl>

然后是一个看起来像这样的ViewModels\RegistrationViewModel.cs

namespace Configurator.ViewModels {
    public class RegistrationViewModel : BindableBase {
        private string _email;
        public string Email {
            get { return _email; }
            set { SetProperty(ref _email, value); }
        }

        private string _password;
        public string Password {
            get { return _password; }
            set { SetProperty(ref _password, value); }
        }

        private string _passwordConfirmation;
        public string PasswordConfirmation {
            get { return _passwordConfirmation; }
            set { SetProperty(ref _passwordConfirmation, value); }
        }

        public DelegateCommand RegisterCommand { get; private set; }

        public RegistrationViewModel() {
            Console.WriteLine("RegistrationViewModel");
            RegisterCommand = new DelegateCommand(Register);
        }

        private void Register() {
            Console.WriteLine("Registering");
            Console.WriteLine($"Email: {Email}");
            Console.WriteLine($"Password: {Password}");
            Console.WriteLine($"Password Confirmation: {PasswordConfirmation}");
        }
    }
}

在跟随 MVVM 时,EmailPasswordPasswordConfirmation 是否应该进入模型?如果它应该进入模型,布线是如何完成的?我找不到任何例子。

【问题讨论】:

  • 为什么投反对票?如果有人在诸如 Rails 之类的 MVC 应用程序上问我这个问题,答案不会是意见问题,即使那样,如何将模型连接到视图我也不认为这是意见问题。如果是这样,指出 MVVC 定义如此松散的事实可能对其他初学者有用,因为那里几乎没有最新的文档。

标签: c# .net wpf prism prism-6


【解决方案1】:

您的实现在我看来一切都很好,即您绑定到视图模型的属性。

有时人们倾向于将视图模型称为“模型”,但在这种情况下,实际模型将由执行实际注册的服务表示。

您可以向视图模型注入此服务实现的接口,然后在 Register() 方法中通过此接口调用服务的方法,例如:

public class RegistrationViewModel : BindableBase
{
    ...
    private readonly IRegistrationService _registrationService;
    public RegistrationViewModel(IRegistrationService registrationService)
    {
        _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
        RegisterCommand = new DelegateCommand(Register);
    }

    private void Register()
    {
        _registrationService.Register(...);
    }
}

【讨论】:

  • 我不知道。显然不知何故不知道 MVVM...现在删除的答案可能会提供线索。
  • +1 来自我。此实现还允许您使用DataTemplateControlTemplate 而不是UserControl,我认为这是最后的手段。
【解决方案2】:

由于您使用的是 MVVM,因此属性应该在模型中。 然后,您在 ViewModel 中创建该模型的属性,使其从 INotifyPropertyChanged 调用 PropertyChanged-Event。

然后,在视图中,您从 ViewModel 中绑定模型属性的元素名称。

然后您应该决定是让您的模型也实现 INotifyPropertyChanged 还是找到其他方法。

【讨论】:

    【解决方案3】:

    您的 ViewModel 和您的 XAML 都很好。是的,您应该将电子邮件、密码等作为 ViewModel 的一部分公开。

    您的示例中缺少的部分是将 ViewModel 绑定到 UI。可以通过在 XAML 中或在代码隐藏页面的构造函数中声明它来实现这一点

    public Registration(RegistrationViewModel model)
    {
        DataContext = model;
    }
    

    你在询问什么接线,因为我觉得这一切都很好。

    【讨论】:

    • 我不知道您为什么被否决,但视图的 DataContext 已由 prism:ViewModelLocator.AutoWireViewModel 附加属性设置。
    • 除此之外,您永远不应该明确设置 UserControl 的 DataContext。 DataContext 应该从其父元素继承,或者由 Prism 等框架自动设置。
    • 再说一次,@Clemens,我也错过了这一点,我盲目地继续,好像 XAML 是为 Window 准备的
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多