【问题标题】:UWP+Prism MVVM - How do I set the value of a view model property via XAML?UWP+Prism MVVM - 如何通过 XAML 设置视图模型属性的值?
【发布时间】:2018-10-09 09:00:53
【问题描述】:

我在视图模型中有一个属性,我希望能够通过 XAML 设置它,但我不知道该怎么做。 我有一个非常基本的用户控件(包含项目列表),其中两个将放置在页面上,我希望能够将一个设置为“源”(由枚举定义),一个设置为成为“目标”。

[下面的代码已经被删减了很多,如果我不小心犯了一些错误或遗漏了一些东西,我们深表歉意。]

我的列举是:

public enum ConversionSide
{
    Source, // Convert something FROM whatever is here.
    Target  // Convert something TO whatever is here.
}

我有一个如下所示的页面:

<Page
    x:Class="MyApp.Views.ConverterPage"
    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:models="using:MyApp.Models"
    xmlns:my="using:MyApp.Controls"
    xmlns:prismMvvm="using:Prism.Windows.Mvvm"
    prismMvvm:ViewModelLocator.AutoWireViewModel="True"
    Style="{StaticResource PageStyle}"
    mc:Ignorable="d">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <my:SelectorPage Name="SourceSelector" Grid.Column="0" />
        <my:SelectorPage Name="TargetSelector" Grid.Column="1" />
    </Grid>

</Page>

...其中 SelectorPage 是一个用户控件(我将其称为“页面”以使 Prism AutoWire 工作,但这不是这里的问题),其中包含一个看起来像这样的项目列表(一切正常)。 ..

<UserControl
    x:Class="MyApp.Controls.SelectorPage"
    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:models="using:MyApp.Models"
    xmlns:my="using:MyApp.Controls"
    xmlns:prismMvvm="using:Prism.Windows.Mvvm"
    prismMvvm:ViewModelLocator.AutoWireViewModel="True"
    mc:Ignorable="d">

    <ListView
        Grid.Column="0"
        ItemsSource="{x:Bind ViewModel.MyList, Mode=OneWay}"
        SelectedItem="{x:Bind ViewModel.MySelectedItem, Mode=TwoWay}">
        <ListView.Header>
            <TextBlock Margin="0,8,0,8" HorizontalAlignment="Center" FontStyle="Italic" Text="Header Text" />
        </ListView.Header>
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="models:MyListItem">
                <my:MyListItemTemplate />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</UserControl>

..后面的代码为...

public sealed partial class SelectorPage : UserControl
{
    private SelectorViewModel ViewModel => DataContext as SelectorViewModel;

    public SelectorPage()
    {
        this.InitializeComponent();
    }
}

SelectorViewModel 看起来像这样...

public class SelectorViewModel : ViewModelBase
{
    private ConversionSide _side;

    public ConversionSide Side
    {
        get { return _side; }
        set { SetProperty(ref _side, value); }
    }

    // Many lines have been omitted for 'clarity'.
}

我希望能够像这样在 XAML 中设置 SelectorViewModel 的 Side 属性...

<my:SelectorPage Name="SourceSelector" Grid.Column="0" Side="Source" />
<my:SelectorPage Name="TargetSelector" Grid.Column="1" Side="Target" />

(一旦设置了 Side,我不希望它改变。)

我该怎么做?

我研究过使用依赖属性,但无法让它更改 SelectorViewModel 中的属性。当我在 SelectorPage 中添加一个时,它在 XAML 中可见并且我可以设置它,但它实际上并没有做任何事情,所以我可能没有正确使用它。在视图模型中放置依赖属性对我来说听起来不对,但我可能是错的。 我浏览了网络 - Microsoft 文档、博客、文章、堆栈溢出等 - 但我找不到任何可以很好地解释事情的东西,让我弄清楚我应该做什么。我发现的著作似乎完全是关于从绑定属性中获取信息的——我同意——但我所追求的是设置来自 XAML 的属性。

谁能给我一些线索吗?我不知道我离得到我想要的东西只有一步之遥,还是离我很远。

【问题讨论】:

  • 您正在另一个视图上使用 SelectorPage 用户控件。该视图还应该有一个视图模型,并且应该有 2 个属性,例如 SelectorViewModel 类型的 SourceSelector 和 TargetSelectoor。只需将每个 SelectorPage 的 DataContext 设置为属性之一
  • 我添加了额外的属性——它们需要是依赖属性吗? - 在 ConverterViewModel (for ConverterPage) - public ConverterPage() { InitializeComponent(); ViewModel.SourceSelectorViewModel = SourceMeasureSelector.ViewModel; ViewModel.TargetSelectorViewModel = TargetMeasureSelector.ViewModel; - 但我不知道如何通过 ConverterPage XAML 为每个设置 Side 属性; Side 属性似乎不可用。我还需要做些什么吗?

标签: c# wpf xaml uwp prism


【解决方案1】:

这会将SelectorPage 控件的Side 属性设置为Source

视图通过双向绑定设置视图模型的属性。例如,当您更改TextBox 中的文本时,以下TextBox 设置名为Test 的视图模型的string 属性:

<TextBox Text="{Binding Test, Mode=TwoWay}" />

因此,从视图设置视图模型的属性通常适用于处理某种输入的控件。源属性的任何默认值都应在视图模型中定义:

private ConversionSide _side = ConversionSide.Source;

您不应该在视图中定义默认值。

【讨论】:

  • 请原谅我在这方面的无知,但我不明白这如何回答我的问题。 SelectorPage 的 Side 属性必须由 ConverterPage 设置 - 或该级别的某些东西 - 因为 SelectorPage 或 SelectorModelView 都不知道它是源还是目标。只有在它们都被创建之后,才需要告诉每个人它是什么。此外,没有任何东西可以绑定到 Side 属性,因为它没有在控件中使用;它仅在视图模型中使用,因此它知道它是哪一个 - 源或目标 - 因此它可以订阅/发布正确的消息。
  • “由 ConverterPage 设置”?这个 MVVM 怎么样?页面是视图。它们不应包含任何应用程序逻辑。
  • SelectorPage 可以设置 ConverterPage 的属性,但不能设置视图模型的属性。
  • 抱歉,我是 UWP 和 MVVM(包括 Prism)的新手,我正在努力学习,但我很难从头开始学习。我知道我应该尽量避免将东西放在视图中(代码隐藏) - 并且到目前为止已经这样做了 - 但我不知道该怎么做。基本上我有两个通过一些静态 XAML 创建的视图模型,一个需要被告知它是源,另一个是目标。你会建议我怎么做?
  • 视图模型的“来源”是什么?
猜你喜欢
  • 2015-12-21
  • 1970-01-01
  • 2018-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多