I've spent the day looking at other questions on this topic and cannot get this particular code to work.
Background: We're using Prism to auto-register viewsmodels for views and inject services using Prism's DI container. The app is structured on reusable user controls. So a specific user control might appear on different windows (or, obviously, multiple instances of the same window). For example, we have a Company window with five different user controls. Each user control's viewmodel must get the CompanyId from the parent window's viewmodel so it can use that CompanyId to call various services, etc.
I'm tried setting up a simple example without Prism but with the Community MVVM Toolkit and haven't had much luck.
The window 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>
Window code-behind:
namespace BindingDependencyProperties
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
Window VM:
namespace BindingDependencyProperties
{
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private string _companyIdFromWin;
public MainWindowViewModel()
{
CompanyIdFromWin = "test123";
}
}
}
User Control 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>
User Control code behind:
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;
}
}
}
User Control VM:
public partial class CompanyUserControlViewModel : ObservableObject
{
[ObservableProperty]
private string _companyId = string.Empty;
}
When I run the app I see:
The CompanyId's aren't flowing into the usercontrol VM. Please note I did try without using the MVVM Toolkit, manually implementing INotifyPropertyChanged and the backing properties and handler with the same result.
So,
- What am I doing wrong here?
- Is this the best way of doing this, given that eventually Prism will be initializing the viewmodels (not CompanyUserControl's constructor) and we don't want tight coupling between windows and user controls.
