I want to create a Custom User control (UserControl) with custom property (MyLabel) in WPF using C# without writing any code behind. But my custom property MyLabel is inaccessible in MainWindow.xaml when I'm using my custom control. What is the problem in my code? If my implementation is wrong then how to achieve this?
UCControl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public class UCControl:UserControl
{
public String MyLabel
{
get { return (String)GetValue(MyLabelProperty); }
set { SetValue(MyLabelProperty, value); }
}
public static readonly DependencyProperty MyLabelProperty =
DependencyProperty
.Register(
"MyLabel",
typeof(string),
typeof(UCControl),
new PropertyMetadata(""));
public UCControl()
{
MyLabel = "default label";
}
}
}
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-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.DataContext>
<local:UCControl/>
</Grid.DataContext>
<TextBlock Text="{Binding MyLabel}" FontSize="18"/>
</Grid>
</UserControl>
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"
Title="MainWindow" Height="450" Width="800">
<Grid >
<local:UserControl1 MyLabel="Hello World"/>
</Grid>
</Window>
The expression
<local:UserControl1 MyLabel="Hello World"/>
requires that MyLabel is a property of the UserControl1 class.
You have to declare the property of the class declaration of UserControl1, i.e. in the file UserControl1.xaml.cs:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public static readonly DependencyProperty MyLabelProperty =
DependencyProperty.Register(
nameof(MyLabel),
typeof(string),
typeof(UserControl1));
public string MyLabel
{
get { return (string)GetValue(MyLabelProperty); }
set { SetValue(MyLabelProperty, value); }
}
}
You would bind to that property in the UserControl's XAML by
<TextBlock Text="{Binding MyLabel,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
Related
i'm learning the MVVM Pattern and have some trouble with Databindings. I understand how it works, but in my example it's using the wrong DataContext to search for the binding.
I did not found another Question that suits to my problem.
So i have this View:
<UserControl x:Class="Kenshinaro.CashRegister.UI.View.CashRegister.CashRegisterChoiceView"
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"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<ItemsControl ItemsSource="{Binding CashRegisters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</UserControl>
With following ViewModel:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kenshinaro.CashRegister.UI.View.CashRegister;
namespace Kenshinaro.CashRegister.UI.ViewModel.CashRegister
{
public class CashRegisterChoiceViewModel : MVVM.ViewModel
{
private ObservableCollection<CashRegisterItemsControlView> _cashRegisters = new ObservableCollection<CashRegisterItemsControlView>()
{
new CashRegisterItemsControlView()
{
DataContext = new CashRegisterItemsControlViewModel()
{
View = new CashRegisterCardView()
{
DataContext = new CashRegisterCardViewModel()
{
Model = new Model.CashRegister()
{
Name = "1"
}
}
}
}
},
new CashRegisterItemsControlView()
{
DataContext = new CashRegisterItemsControlViewModel()
{
View = new CashRegisterCardView()
{
DataContext = new CashRegisterCardViewModel()
{
Model = new Model.CashRegister()
{
Name = "2"
}
}
}
}
},
new CashRegisterItemsControlView()
{
DataContext = new CashRegisterItemsControlViewModel()
{
View = new CashRegisterCardView()
{
DataContext = new CashRegisterCardViewModel()
{
Model = new Model.CashRegister()
{
Name = "3"
}
}
}
}
}
};
public ObservableCollection<CashRegisterItemsControlView> CashRegisters
{
get => _cashRegisters;
set => SetProperty(ref _cashRegisters, value);
}
}
}
(My Base ViewModel class is implementing the INotifyPropertyChanged interface)
So this View shows a list of this view:
<UserControl x:Class="Kenshinaro.CashRegister.UI.View.CashRegister.CashRegisterItemsControlView"
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:Kenshinaro.CashRegister.UI.View.CashRegister"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<md:Card Margin="10">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<local:CashRegisterCardView Padding="5"/>
<Button Margin="20" Grid.Row="1" Content="Pick me"/>
</Grid>
</md:Card>
</UserControl>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kenshinaro.CashRegister.UI.ViewModel.CashRegister
{
public class CashRegisterItemsControlViewModel : MVVM.ViewModel
{
private View.CashRegister.CashRegisterCardView _view;
public View.CashRegister.CashRegisterCardView View
{
get => _view;
set => SetProperty(ref _view, value);
}
}
}
And this View shows also this view:
<UserControl x:Class="Kenshinaro.CashRegister.UI.View.CashRegister.CashRegisterCardView"
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:Kenshinaro.CashRegister.UI.View.CashRegister"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Background="White" >
<Grid>
<TextBlock Text="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=local:CashRegisterCardView}}"/>
</Grid>
</UserControl>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kenshinaro.CashRegister.Model;
namespace Kenshinaro.CashRegister.UI.ViewModel.CashRegister
{
public class CashRegisterCardViewModel : MVVM.ViewModel
{
private Model.CashRegister _model;
public Model.CashRegister Model
{
get => _model;
set => SetProperty(ref _model, value);
}
public String Name
{
get => _model.Name;
set => _model.Name = value;
}
}
}
Now if I start the App the Binding on the TextBlock in the last view doesn't appear.
The Output of VisualStudio says:
System.Windows.Data Error: 40 : BindingExpression path error: 'Name' property not found on 'object' ''CashRegisterItemsControlViewModel' (HashCode=35528341)'. BindingExpression:Path=DataContext.Name; DataItem='CashRegisterCardView' (Name=''); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
As I can get out of it, it is searching for the Property in the DataContext of CashRegisterItemsControlView but I just don't understand why, because i set the DataContext manually on collection initialization (Just for testing):
private ObservableCollection<CashRegisterItemsControlView> _cashRegisters = new ObservableCollection<CashRegisterItemsControlView>()
{
new CashRegisterItemsControlView()
{
DataContext = new CashRegisterItemsControlViewModel()
{
View = new CashRegisterCardView()
{
DataContext = new CashRegisterCardViewModel()
{
Model = new Model.CashRegister()
{
Name = "1"
}
}
}
}
},
...
So why it's still taking the wrong DataContext?
Now when i change the Binding to View.DataContext.Name it's searching in the manually set DataContext:
System.Windows.Data Error: 40 : BindingExpression path error: 'View' property not found on 'object' ''CashRegisterCardView' (Name='')'. BindingExpression:Path=View.DataContext.Name; DataItem='CashRegisterCardView' (Name=''); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
I'm really confused.. I hope you can help me.
Thanks!
If you need information about the other classes just ask. I don't want to put more code into the question as it just long enough.
View models have references to views. This is a violation of MVVM pattern.
The root of problem is in the CashRegisterItemsControlView implementation:
<UserControl x:Class="Kenshinaro.CashRegister.UI.View.CashRegister.CashRegisterItemsControlView"
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:Kenshinaro.CashRegister.UI.View.CashRegister"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<md:Card Margin="10">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<local:CashRegisterCardView Padding="5"/>
<Button Margin="20" Grid.Row="1" Content="Pick me"/>
</Grid>
</md:Card>
</UserControl>
it creates an instance of CashRegisterCardView (<local:CashRegisterCardView Padding="5"/>) which doesn't have its own DataContext, and inherits DataContext from parent. View from CashRegisterItemsControlViewModel is not used.
You can change it to make it work, like this:
<UserControl x:Class="Kenshinaro.CashRegister.UI.View.CashRegister.CashRegisterItemsControlView"
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:Kenshinaro.CashRegister.UI.View.CashRegister"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<md:Card Margin="10">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentControl Content="{Binding View}" Padding="5"/>
<Button Margin="20" Grid.Row="1" Content="Pick me"/>
</Grid>
</md:Card>
</UserControl>
but it would be much better to rework your app architecture
I'm learning UWP User Control and facing the below code:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="Blue" />
</StackPanel>
</Page>
I have defined a user control with three dependency properties, Username, Password, and fillcolor. The below code shows my user control xaml
<UserControl
x:Name="myctrl"
x:Class="LearningUWP.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<RelativePanel>
<Rectangle Fill="{Binding fillcolor, ElementName=myctrl}" x:Name="Rec" Height="100" RelativePanel.AlignRightWithPanel="True" />
<TextBlock Text="Username_lbl" RelativePanel.AlignRightWithPanel="True" TextAlignment="Center" RelativePanel.Below="Rec" x:Name="Username_lb" Margin="0,50,0,0" RelativePanel.AlignLeftWithPanel="True" />
<TextBox x:Name="Username_input" RelativePanel.Below="Username_lb" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" Text="{Binding Username, ElementName=myctrl}" ></TextBox>
<TextBlock Text="Password_lbl" x:Name="Password_lb" RelativePanel.AlignRightWithPanel="True" TextAlignment="Center" RelativePanel.Below="Username_input" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" ></TextBlock>
<TextBox x:Name="Password_input" RelativePanel.Below="Password_lb" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignLeftWithPanel="True" Margin="0,20,0,0" Text="{Binding Password, ElementName=myctrl}" ></TextBox>
</RelativePanel>
</UserControl>
and the code-behind:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace LearningUWP
{
public sealed partial class MyUserControl : UserControl
{
public MyUserControl()
{
this.InitializeComponent();
}
public string Username
{
get { return (string)GetValue(UsernameProperty); }
set { SetValue(UsernameProperty, value); }
}
public static readonly DependencyProperty UsernameProperty =
DependencyProperty.Register("Username", typeof(string), typeof(MyUserControl), null);
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(MyUserControl), null);
public string fillcolor
{
get { return (string)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(string), typeof(MyUserControl), null);
}
}
The Username and Password are working as I can see "aaa" and "bbb" on my screen, but the color is not working. How to solve it?
UPDATE1
I modified the fillcolor property to the below code:
public Brush fillcolor
{
get { return (Brush)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(Brush), typeof(MyUserControl), null);
But it's still not working.
UPDATE2
I updated the MainPage.xaml shown in the below:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<SolidColorBrush x:Key="MyBlueColor" Color="#0000FF"/>
</Page.Resources>
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="{StaticResource MyBlueColor}" />
</StackPanel>
</Page>
But it's still not working.
Your binding seems correct, your problem is in the Type of your 'fillcolor' property.
You are binding it as a string, whereas you should bind it as a Brush
public Brush fillcolor
{
get { return (Brush)GetValue(fillcolorProperty); }
set { SetValue(fillcolorProperty, value); }
}
public static readonly DependencyProperty fillcolorProperty =
DependencyProperty.Register("fillcolor", typeof(Brush), typeof(MyUserControl), null);
The Fill property requires a Brush to work properly as you can see in here Shape.Fill
I forgot to mention that you don't need to specify the element name in this case as you are using your code behind as a 'ViewModel', so, the code below will do the trick for you:
<Rectangle Fill="{x:Bind fillcolor}" x:Name="Rec" Height="100" RelativePanel.AlignRightWithPanel="True" />
Furthermore, you need to specify the Brush in your page's resources as a solid color brush, so you could write:
<Page
x:Class="LearningUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearningUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<SolidColorBrush x:Key="MyBlueColor" Color="#0000FF"/> <!-- or Blue -->
</Page.Resources>
<StackPanel>
<local:MyUserControl Username="aaa" Password="bbb" fillcolor="{StaticResource MyBlueColor}" />
</StackPanel>
</Page>
And, according to difference-between-binding-and-xbind
We need to use x:Bind Binding does not support framework elements.
Well I made my custom usercontrol which is "simply" a combination of a label and a textbox.
<UserControl x:Class="testit.LabelTextBox"
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"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="300">
<DockPanel LastChildFill="False">
<TextBox x:Name="textBox" TextWrapping="Wrap" DockPanel.Dock="Right" VerticalAlignment="Center" Text="{Binding TextBoxText}" />
<Label x:Name="label" DockPanel.Dock="Right" Target="{x:Reference textBox}" HorizontalAlignment="Right" VerticalAlignment="Center" Content="Label Text"/>
</DockPanel>
</UserControl>
I then created a usercontrol class with the dependecy property:
using System.Windows;
using System.Windows.Controls;
namespace simtest
{
/// <summary>
/// Interaction logic for LabelTextBox.xaml
/// </summary>
public partial class LabelTextBox : UserControl
{
public string TextBoxText {
get { return (string)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
public readonly static DependencyProperty TextBoxTextProperty =
DependencyProperty.Register("TextBoxTextProperty",
typeof(string), typeof(LabelTextBox), new UIPropertyMetadata(null));
public LabelTextBox() {
InitializeComponent();
DataContext = this;
}
}
}
Now this "works" as in that it compiles. And if I use above control as:
<local:LabelTextBox TextBoxText="foobar"></local:LabelTextBox>
It will show correctly - while running -.
However I need this for each and every element of the textbox I wish to be able to adapt - height width etc etc. This isn't really ideal: can I make it so that I can just edit the LabelTextBox' TextBox directly?
I have a test application wich consists on two Windows and a UserControl.
I want to insert the control in each Window using the same DataContext:
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:WpfApplication2.View"
xmlns:viewModel="clr-namespace:WpfApplication2.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<viewModel:ControlColorViewModel x:Name="dataContext1"/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Width="64" Height="64" Command="{Binding
Path=PressedButton}">Press</Button>
<view:ControlColor Grid.Column="1" />
</Grid>
</Window>
ControlColor.xaml:
<UserControl x:Class="WpfApplication2.View.ControlColor"
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:viewModel="clr-namespace:WpfApplication2.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="{Binding Path=BackgroundColor}">
</Grid>
</UserControl>
ControlColorViewModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Input;
namespace WpfApplication2.ViewModel
{
class ControlColorViewModel : ViewModelBase
{
private Brush backgroundColor;
public Brush BackgroundColor
{
get { return this.backgroundColor; }
set
{
if (this.backgroundColor != value)
{
this.backgroundColor = value;
OnPropertyChanged("BackgroundColor");
}
}
}
public ICommand PressedButton { get { return new RelayCommand(param =>
this.SetPressedButton()); } }
public ControlColorViewModel()
{
}
private void SetPressedButton()
{
BackgroundColor = Brushes.Orange;
}
}
}
Window2.xaml:
<Window x:Class="WpfApplication2.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:WpfApplication2.View"
Title="Window2" Height="300" Width="300">
<Grid>
<view:ControlColor />
</Grid>
</Window>
When the button is pressed the background in the ContentControl in the MainWindow gets orange, and i want the same for the ContentControl inserted in Window2. Using the same datacontext.
How can i get the same datacontext used in MainWindow?
Thanks in advance.
There are a lot of ways. The easy is to have a common, shared model property (CommonModel) and send it to every ViewModels.
Next step is to use EventAggregator, but to my mind it's too complicated for you..
I'm a little new to WPF (having more of a WinForms background), but if I understand correctly you could define your dataContext1 in the App file resources and then they both could reference it.
You can use something called Dependency Injection to get your controls to use the same DataContext.
Basically, you need to take it out of the XAML and 'find/resolve' your shared ControlColorViewModel in the constructor for your controls.
I am using Caliburn Micro with WPF. I want to create an application with a menu on the left side, and a grid on the right side of the application. When clicking on a menu item, the grid on the right side, will change to another view. The another view will be in a separate file.
MainWindowView:
<UserControl x:Class="CMDemo.Views.MainWindowView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90*" />
<ColumnDefinition Width="210*" />
</Grid.ColumnDefinitions>
<StackPanel Name="LeftMenu">
<Button Name="ChangeDisplay" Content="Click Me"></Button>
<TextBlock x:Name="MyString"></TextBlock>
</StackPanel>
<Grid Grid.Column="1" x:Name="MainGridContent" />
</Grid>
MainWindowViewModel:
public class MainWindowViewModel : PropertyChangedBase
{
private UserControl mainGridContent;
private string myString;
public UserControl MainGridContent
{
get { return this.mainGridContent; }
set
{
this.mainGridContent = value;
NotifyOfPropertyChange(() => this.MainGridContent);
}
}
public string MyString
{
get { return this.myString; }
set
{
this.myString = value;
NotifyOfPropertyChange(() => this.MyString);
}
}
public void ChangeDisplay()
{
this.MainGridContent = new ChangeDisplayView();
this.MyString = "Testing....";
}
}
The changeDisplayViewModel:
public class changeDisplayViewModel: PropertyChangedBase
{
}
The changeDisplayView:
<UserControl x:Class="CMDemo.Views.changeDisplayView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox content="Hello Caliburn Micro">
</Grid>
When I click the "Click Me" button the TextBlock "MyString" is updated and showing, but the usercontrol is not. What am I doing wrong?
Try changing MainGridContent to a changeDisplayViewModel rather than the view itself.