将值从窗口传递到子用户控件

问题描述 投票:0回答:1

我花了一天的时间查看有关该主题的其他问题,但无法使该特定代码正常工作。

背景:我们使用 Prism 自动注册视图的视图模型,并使用 Prism 的 DI 容器注入服务。该应用程序基于可重用的用户控件构建。因此,特定的用户控件可能会出现在不同的窗口上(或者显然,同一窗口的多个实例)。例如,我们有一个带有五个不同用户控件的公司窗口。每个用户控件的视图模型必须从父窗口的视图模型获取 CompanyId,以便它可以使用该 CompanyId 来调用各种服务等。

我尝试在没有 Prism 的情况下使用社区 MVVM 工具包设置一个简单的示例,但运气不佳。

窗口 XAML:

<Window
    x:Class="BindingDependencyProperties.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:local="clr-namespace:BindingDependencyProperties"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">
            <Run Text="{Binding CompanyIdFromWin}" />
        </TextBlock>
        <local:CompanyUserControl Grid.Row="1" CompanyId="{Binding CompanyIdFromWin}" />
        <local:CompanyUserControl Grid.Row="2" CompanyId="hardcoded" />
    </Grid>
</Window>

窗口代码隐藏:

namespace BindingDependencyProperties
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

窗口虚拟机:

namespace BindingDependencyProperties
{
    public partial class MainWindowViewModel : ObservableObject
    {
        [ObservableProperty]
        private string _companyIdFromWin;

        public MainWindowViewModel()
        {
            CompanyIdFromWin  = "test123";
        }
    }
}

用户控制XAML:

<UserControl x:Class="BindingDependencyProperties.CompanyUserControl"
             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:local="clr-namespace:BindingDependencyProperties"
                 d:DataContext="{d:DesignInstance Type=local:CompanyUserControlViewModel, IsDesignTimeCreatable=True}"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock>
            <Run Text="Company ID: " />
            <Run Text="{Binding CompanyId}" />
        </TextBlock>
    </Grid>
</UserControl>

背后的用户控制代码:

namespace BindingDependencyProperties
{
    public partial class CompanyUserControl : UserControl
    {
        private CompanyUserControlViewModel _viewModel;

        public string CompanyId
        {
            get { return (string)GetValue(CompanyIdProperty); }
            set { SetValue(CompanyIdProperty, value); }
        }

        public static readonly DependencyProperty CompanyIdProperty =
            DependencyProperty.Register("CompanyId", typeof(string), typeof(CompanyUserControl),
                new PropertyMetadata(string.Empty));

        public CompanyUserControl()
        {
            InitializeComponent();
            _viewModel = new CompanyUserControlViewModel();
            this.DataContext = _viewModel;
        }
    }
}

用户控制虚拟机:

    public partial class CompanyUserControlViewModel : ObservableObject
    {
        [ObservableProperty]
        private string _companyId = string.Empty;

    }

当我运行应用程序时,我看到:

App output

CompanyId 没有流入用户控制虚拟机。请注意,我确实尝试不使用 MVVM Toolkit,手动实现 INotifyPropertyChanged 以及支持属性和处理程序,但结果相同。

那么,

  1. 我在这里做错了什么?
  2. 考虑到最终 Prism 将初始化视图模型(而不是 CompanyUserControl 的构造函数)并且我们不希望窗口和用户控件之间紧密耦合,这是最好的方法吗?
wpf mvvm prism dependency-properties
1个回答
0
投票

我在这里做错了什么?

public CompanyUserControl()
{
    InitializeComponent();
    _viewModel = new CompanyUserControlViewModel();
    this.DataContext = _viewModel;
}

这不是一个可重用的控件,它非常具体和专业。没关系,所有应用程序都有它,主要用于顶级视图或页面。这些还利用 Prism 的视图模型定位器。

但是,在您的情况下,您希望控件从其他人那里接收其视图模型,例如通过将

ItemsControl
ItemsSource
绑定到父视图模型上的集合属性,并通过
ItemTemplate
创建控件。

© www.soinside.com 2019 - 2024. All rights reserved.