WinUI 3 Binding from a DataTemplate to the parent ViewModel - c#

In a WinUI 3 application, using CommunityToolkit.Mvvm, I have XXXPage which has a ListDetailsView.
I defined a DateTemplate for the ListDetailsView DetailsTemplate, which contains a user control : XXXDetailControl.
I am trying to bind the InstallClicked event of the XXXDetailControl to the page's ViewModel InstallCommand, with no success.
<DataTemplate x:Key="DetailsTemplate">
<Grid>
<views:XXXDetailControl
DetailMenuItem="{Binding}"
InstallClicked="{ ???? }" />
</Grid>
...
</DataTemplate>
How can I setup this binding so that the event from the control defined in the DataTemplate is binded to the page viewmodel command ? How can I setup this binding so that the selected item is sent with the event ?
XXXPage.xaml :
<Page
x:Class="XXXPage"
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:XXX.Models"
xmlns:views="using:XXX.Views"
xmlns:behaviors="using:XXX.Behaviors"
xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:viewmodels="using:XXX.ViewModels"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
mc:Ignorable="d">
<Page.Resources>
...
<DataTemplate x:Key="DetailsTemplate">
<Grid>
<views:XXXDetailControl
DetailMenuItem="{Binding}"
InstallClicked="{Binding ViewModel.InstallCommand, ElementName=?}" CommandParameter="{x:Bind (viewmodels:XXXDetailViewModel)}" />
</Grid>
...
</DataTemplate>
</Page.Resources>
<Grid x:Name="ContentArea">
...
<controls:ListDetailsView
x:Uid="ListDetails"
x:Name="ListDetailsViewControl"
DetailsTemplate="{StaticResource DetailsTemplate}"
ItemsSource="{x:Bind ViewModel.Items}"/>
</Grid>
</Page>
XXXPage.cs :
public sealed partial class XXXPage: Page
{
public XXXViewModel ViewModel
{
get;
}
public XXXPage()
{
ViewModel = App.GetService<XXXViewModel >();
InitializeComponent();
}
}
the XXXViewModel :
public class XXXViewModel : ObservableRecipient, INavigationAware
{
private XXXDetailViewModel? _selected;
public XXXDetailViewModel? Selected
{
get => _selected;
set
{
SetProperty(ref _selected, value);
}
}
public ObservableCollection<XXXDetailViewModel> Items { get; private set; } = new ObservableCollection<XXXDetailViewModel>();
public ICommand InstallCommand;
}

If you can use Command and CommandParameter inside your user control, you can do it this way.
DetailsControl.xaml.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Windows.Input;
namespace CustomControlEvent;
public sealed partial class DetailControl : UserControl
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
nameof(Text),
typeof(string),
typeof(DetailControl),
new PropertyMetadata(default));
public static readonly DependencyProperty ClickCommandProperty = DependencyProperty.Register(
nameof(ClickCommand),
typeof(ICommand),
typeof(DetailControl),
new PropertyMetadata(default));
public static readonly DependencyProperty ClickCommandParameterProperty = DependencyProperty.Register(
nameof(ClickCommandParameter),
typeof(object),
typeof(DetailControl),
new PropertyMetadata(default));
public DetailControl()
{
this.InitializeComponent();
}
public object ClickCommandParameter
{
get => (object)GetValue(ClickCommandParameterProperty);
set => SetValue(ClickCommandParameterProperty, value);
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public ICommand ClickCommand
{
get => (ICommand)GetValue(ClickCommandProperty);
set => SetValue(ClickCommandProperty, value);
}
}
DetailsControl.xaml
<UserControl
x:Class="CustomControlEvent.DetailControl"
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="using:CustomControlEvent"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Button
Command="{x:Bind ClickCommand, Mode=OneWay}"
CommandParameter="{x:Bind ClickCommandParameter, Mode=OneWay}"
Content="{x:Bind Text, Mode=OneWay}" />
</Grid>
</UserControl>
MainPageViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
namespace CustomControlEvent;
public partial class MainPageViewModel : ObservableObject
{
[RelayCommand]
private void Run(object commandParameter)
{
}
[ObservableProperty]
private ObservableCollection<DetailsViewModel> items = new()
{
new DetailsViewModel() { Details = "A" },
new DetailsViewModel() { Details = "B" },
new DetailsViewModel() { Details = "C" },
};
}
MainPage.xaml.cs
using Microsoft.UI.Xaml.Controls;
namespace CustomControlEvent;
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public MainPageViewModel ViewModel { get; } = new();
}
MainPage.xaml
This page is named ThisPage in order to bind from the DataTemplate.
<Page
x:Class="CustomControlEvent.MainPage"
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="using:CustomControlEvent"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="ThisPage"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<StackPanel>
<StackPanel.Resources>
<DataTemplate
x:Key="DetailsTemplate"
x:DataType="local:DetailsViewModel">
<Grid>
<local:DetailControl
ClickCommand="{Binding ElementName=ThisPage, Path=ViewModel.RunCommand}"
ClickCommandParameter="{x:Bind}"
Text="{x:Bind Details, Mode=OneWay}" />
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ListView
ItemTemplate="{StaticResource DetailsTemplate}"
ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}" />
</StackPanel>
</Page>

Did you try to give the Page a Name like this?:
<Page ...
Name="thePage">
<Page.Resources>
...
<DataTemplate x:Key="DetailsTemplate">
<Grid>
<views:XXXDetailControl
DetailMenuItem="{Binding}"
InstallClicked="{Binding ViewModel.InstallCommand, ElementName=thePage}" ... />
</Grid>
...
</DataTemplate>
</Page.Resources>
This seems to work for a ListView.

Related

WinUI 3 - How to open a control in a page upon click of button from a User Control c#?

I have an ItemsRepeater on the page's XAML code where it's ItemsSource property is bind to a list of User Control (ObersvableCollection), a custom control I made. In this User Control there's a button that I wish would open a SplitView pane that I set in the Page's Xaml code. I'm thinking I need to get an instance of the page in the User Control's code behind, on the click event, but I have no idea how.
You can do it this way.
TestUserControl.xaml.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Windows.Input;
namespace WinUI3App1;
public sealed partial class TestUserControl : UserControl
{
public static readonly DependencyProperty ClickCommandProperty = DependencyProperty.Register(
nameof(ClickCommand),
typeof(ICommand),
typeof(TestUserControl),
new PropertyMetadata(null));
public TestUserControl()
{
InitializeComponent();
}
public ICommand ClickCommand
{
get => (ICommand)GetValue(ClickCommandProperty);
set => SetValue(ClickCommandProperty, value);
}
}
TestUseControl.xaml
<UserControl
x:Class="WinUI3App1.TestUserControl"
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"
mc:Ignorable="d"
x:Name="ThisControl">
<StackPanel Orientation="Horizontal">
<Button Command="{x:Bind ClickCommand}" CommandParameter="{Binding ElementName=ThisControl}" Content="Click" />
</StackPanel>
</UserControl>
MainWindow.xaml.cs
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace WinUI3App1;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Install the CommunityToolkit.Mvvm NuGet package
// to avoid implementing commands yourself.
ClickCommand = new RelayCommand<TestUserControl>(OnClick);
for (int i = 0; i < 10; i++)
{
TestUserControls.Add(new TestUserControl()
{
ClickCommand = ClickCommand
});
}
}
public ObservableCollection<TestUserControl> TestUserControls { get; set; } = new();
public ICommand ClickCommand { get; set; }
private void OnClick(TestUserControl? sender)
{
SplitViewControl.IsPaneOpen = true;
}
}
MainWindow.xaml
<Window
x:Class="WinUI3App1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<SplitView x:Name="SplitViewControl">
<SplitView.Pane>
<Grid/>
</SplitView.Pane>
<StackPanel Orientation="Vertical">
<ItemsRepeater ItemsSource="{x:Bind TestUserControls}" />
</StackPanel>
</SplitView>
</Window>

WPF Usercontrol Bindings with MVVM ViewModel not working

I've spent some time trying to solve this problem but couldn't find a solution.
I am trying to bind commands and data inside an user control to my view model. The user control is located inside a window for navigation purposes.
For simplicity I don't want to work with Code-Behind (unless it is unavoidable) and pass all events of the buttons via the ViewModel directly to the controller. Therefore code-behind is unchanged everywhere.
The problem is that any binding I do in the UserControl is ignored.
So the corresponding controller method is never called for the command binding and the data is not displayed in the view for the data binding. And this although the DataContext is set in the controllers.
Interestingly, if I make the view a Window instead of a UserControl and call it initially, everything works.
Does anyone have an idea what the problem could be?
Window.xaml (shortened)
<Window x:Class="Client.Views.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Client.Views"
mc:Ignorable="d">
<Window.Resources>
<local:SubmoduleSelector x:Key="TemplateSelector" />
</Window.Resources>
<Grid>
<StackPanel>
<Button Command="{Binding OpenUserControlCommand}"/>
</StackPanel>
<ContentControl Content="{Binding ActiveViewModel}" ContentTemplateSelector="{StaticResource TemplateSelector}">
<ContentControl.Resources>
<DataTemplate x:Key="userControlTemplate">
<local:UserControl />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
</Window>
MainWindowViewModel (shortened)
namespace Client.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
private ViewModelBase mActiveViewModel;
public ICommand OpenUserControlCommand { get; set; }
public ViewModelBase ActiveViewModel
{
get { return mActiveViewModel; }
set
{
if (mActiveViewModel == value)
return;
mActiveViewModel = value;
OnPropertyChanged("ActiveViewModel");
}
}
}
}
MainWindowController (shortened)
namespace Client.Controllers
{
public class MainWindowController
{
private readonly MainWindow mView;
private readonly MainWindowViewModel mViewModel;
public MainWindowController(MainWindowViewModel mViewModel, MainWindow mView)
{
this.mViewModel = mViewModel;
this.mView = mView;
this.mView.DataContext = mViewModel;
this.mViewModel.OpenUserControlCommand = new RelayCommand(ExecuteOpenUserControlCommand);
}
private void OpenUserControlCommand(object obj)
{
var userControlController = Container.Resolve<UserControlController>(); // Get Controller instance with dependency injection
mViewModel.ActiveViewModel = userControlController.Initialize();
}
}
}
UserControlSub.xaml (shortened)
<UserControl x:Class="Client.Views.UserControlSub"
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:local="clr-namespace:Client.Views"
xmlns:viewModels="clr-namespace:Client.ViewModels"
mc:Ignorable="d">
<Grid>
<ListBox ItemsSource="{Binding Models}" SelectedItem="{Binding SelectedModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Attr}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel>
<Button Command="{Binding Add}">Kategorie hinzufügen</Button>
</StackPanel>
</Grid>
</UserControl>
UserControlViewModel (shortened)
namespace Client.ViewModels
{
public class UserControlViewModel : ViewModelBase
{
private Data _selectedModel;
public ObservableCollection<Data> Models { get; set; } = new ObservableCollection<Data>();
public Data SelectedModel
{
get => _selectedModel;
set
{
if (value == _selectedModel) return;
_selectedModel= value;
OnPropertyChanged("SelectedModel");
}
}
public ICommand Add { get; set; }
}
}
UserControlController (shortened)
namespace Client.Controllers
{
public class UserControlController
{
private readonly UserControlSub mView;
private readonly UserControlViewModel mViewModel;
public UserControlController(UserControlViewModel mViewModel, UserControlSub mView)
{
this.mViewModel = mViewModel;
this.mView = mView;
this.mView.DataContext = mViewModel;
this.mViewModel.Add = new RelayCommand(ExecuteAddCommand);
}
private void ExecuteAddCommand(object obj)
{
Console.WriteLine("This code gets never called!");
}
public override ViewModelBase Initialize()
{
foreach (var mod in server.GetAll())
{
mViewModel.Models.Add(mod);
}
return mViewModel;
}
}
}

Adding initialized ViewModels to ObservableCollection displaying null property values

When adding ViewModels to an ObservableCollection, which is shown on the MainWindow as an ItemsControl with the ObservableCollection as the ItemsSource. The initial values of the View are displayed as null. I know this because on debugging and changing the value of the TextBox I see that the Name field is set to null, but when I press the button to add new ViewModels it is setting the Name field but then not displaying the name. This app has been condensed for ease of debugging. So it seems that while the ObservableCollection is communicating to the view it is not receiving the proper values somehow.
MainWindow
<Window x:Class="LifeCalculator.Views.MainWindow"
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"
xmlns:myControl="clr-namespace:LifeCalculator.Views" xmlns:views="clr-namespace:LifeFinanceCalculator.Views"
Title="{Binding Title}" Height="350" Width="525">
<Grid>
<Button Margin="47,24,373,269" Content="Add ViewModels" Command="{Binding AddCommandItem}"/>
<ScrollViewer Margin="28,75,37,72">
<ItemsControl ItemsSource="{Binding ListExampleItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<views:exampleView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
MainWindowViewModel
using Prism.Mvvm;
using System.Collections.ObjectModel;
using LifeFinanceCalculator.ViewModels;
using System.Windows.Input;
using Prism.Commands;
namespace LifeCalculator.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private ObservableCollection<exampleViewModel> _listExampleItems;
public ObservableCollection<exampleViewModel> ListExampleItems
{
get => _listExampleItems;
set
{
SetProperty(ref _listExampleItems, value);
}
}
public ICommand AddCommandItem { get; set; }
public MainWindowViewModel()
{
_listExampleItems = new ObservableCollection<exampleViewModel>();
AddCommandItem = new DelegateCommand(ListItem);
}
private void ListItem()
{
_listExampleItems.Add(new exampleViewModel() { Name = "Chris" });
_listExampleItems.Add(new exampleViewModel() { Name = "Olivia" });
}
}
}
exampleView
<UserControl x:Class="LifeFinanceCalculator.Views.exampleView"
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>
<TextBox Text="{Binding Name}" FontSize="22"/>
</Grid>
</UserControl>
exampleViewModel
using Prism.Mvvm;
namespace LifeFinanceCalculator.ViewModels
{
public class exampleViewModel : BindableBase
{
private string _name;
public string Name
{
get => _name;
set
{
SetProperty(ref _name, value);
}
}
public exampleViewModel()
{
}
}
}
The ViewModelLocator used by Prism was the issue. The ViewModelLocator re-intializes the View with a new ViewModel. To solve the issue :
prism:ViewModelLocator.AutoWireViewModel = "False"

Usercontrol binding lost on value updated, that doesn't happen with standard textbox control

I have a problem with binding in usercontrol.
This is my usercontrol:
UserControl1.xaml
<UserControl x:Class="WpfApp1.UserControl1"
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-ompatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
x:Name="usercontrol"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Text="{Binding HmiField, ElementName=usercontrol}"/>
</Grid>
</UserControl>
UserControl1.xaml.cs
namespace WpfApp1
{
public partial class UserControl1 : UserControl
{
public double HmiField
{
get { return (double)GetValue(HmiFieldProperty); }
set { SetValue(HmiFieldProperty, value); }
}
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register("HmiField", typeof(double), typeof(UserControl1));
public UserControl1()
{
InitializeComponent();
}
}
}
And this is the main window:
MainWindow.xaml
<Window x:Class="WpfApp1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
DataContext="{Binding Md, RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<UniformGrid>
<Button Content="{Binding Prop1}" Click="Button_Click"/>
<Label Content="{Binding Prop1}"/>
<TextBox Text="{Binding Prop1}"/>
<local:UserControl1 HmiField="{Binding Prop1}"/>
</UniformGrid>
</Window>
MainWindow.xaml.cs
namespace WpfApp1
{
public class tMd: INotifyPropertyChanged
{
#region Interfaccia INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
#endregion
private double prop1;
public double Prop1 { get
{
return prop1;
}
set
{
if (prop1 != value)
{
prop1 = value;
NotifyPropertyChanged("Prop1");
}
}
}
}
public partial class MainWindow : Window
{
public tMd Md
{
get { return (tMd)GetValue(MdProperty); }
set { SetValue(MdProperty, value); }
}
public static readonly DependencyProperty MdProperty =
DependencyProperty.Register("Md", typeof(tMd), typeof(MainWindow), new PropertyMetadata(new tMd()));
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Md.Prop1 = 1234.5678;
}
}
}
I found some similar question:
How do I change TextBox.Text without losing the binding in WPF?
WPF: Binding is lost when bindings are updated
WPF Textbox TwoWay binding in datatemplate not updating the source even on LostFocus
But I can't completely understand what's happening: why a standard textbox work as expected and my usercontrol no?
Or better: is there a way to have my usercontrol works with the textbox's behaviour?
The Binding must be TwoWay, either set explicitly
<local:UserControl1 HmiField="{Binding Prop1, Mode=TwoWay}"/>
or implicitly by default:
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register(
nameof(HmiField), typeof(double), typeof(UserControl1),
new FrameworkPropertyMetadata(
0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
A TextBox's Text property is registered like shown above, i.e. with the BindsTwoWayByDefault flag.
At the TextBox Binding in the UserControl's XAML you may also want to update the source property while the user is typing (instead of only on lost focus):
<TextBox Text="{Binding HmiField,
ElementName=usercontrol,
UpdateSourceTrigger=PropertyChanged}"/>
or without the otherwise useless generated usercontrol field:
<TextBox Text="{Binding HmiField,
RelativeSource={RelativeSource AncestorType=UserControl}
UpdateSourceTrigger=PropertyChanged}"/>
Your Prop1 notifies when it changes, but you haven't told you binding to trigger on that notification.
Try including UpdateSourceTrigger=PropertyChanged in you binding

Specify Binding of DependencyProperty in UserControl itself

Following up on my previous question (Change brushes based on ViewModel property)
In my UserControl I have have a DependencyObject. I want to bind that object to a property of my ViewModel. In this case a CarViewModel, property name is Status and returns an enum value.
public partial class CarView : UserControl
{
public CarStatus Status
{
get { return (CarStatus)GetValue(CarStatusProperty); }
set { SetValue(CarStatusProperty, value); }
}
public static readonly DependencyProperty CarStatusProperty =
DependencyProperty.Register("Status", typeof(CarStatus), typeof(CarView), new PropertyMetadata(OnStatusChanged));
private static void OnStatusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var control = (CarView)obj;
control.LoadThemeResources((CarStatus)e.NewValue == CarStatus.Sold);
}
public void LoadThemeResources(bool isSold)
{
// change some brushes
}
}
<UserControl x:Class="MySolution.Views.CarView"
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:views="clr-MySolution.Views"
mc:Ignorable="d"
views:CarView.Status="{Binding Status}">
<UserControl.Resources>
</UserControl.Resources>
<Grid>
<TextBlock Text="{Binding Brand}"FontSize="22" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<UserControl
Where do I need to specify this binding? In the root of the UserControl it gives an error:
The attachable property 'Status' was not found in type 'CarView'
In my MainWindow I bind the CarView using a ContentControl:
<ContentControl
Content="{Binding CurrentCar}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type viewmodel:CarViewModel}">
<views:CarView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
My ViewModel:
[ImplementPropertyChanged]
public class CarViewModel
{
public Car Car { get; private set; }
public CarStatus Status
{
get
{
if (_sold) return CarStatus.Sold;
return CarStatus.NotSold;
}
}
}
your binding isn't well written. instead of writing views:CarView.Status="{Binding Status}" you should write only Status="{Binding Status}"
It seems that your Control is binding to itself.
Status is looked for in CarView.
You should have a line of code in your control CodeBehind like :
this.DataContext = new ViewModelObjectWithStatusPropertyToBindFrom();
Regards

Categories