Design Time Data for Dependency Properties? - wpf

I am building a UserControl that has several DependencyProperties that I use for the bindings of the XAML of the control.
When I work with MVVM I normally create a design time ViewModel, because I find that way it is easier to setup the layout of my Views without having to run the application.
Is there a way to set design time data to my dependency properties in an UserControl?

In yourxaml, define this
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance prefix:ViewModel}"
That should give you the properties in the ViewModel..

I suggest setting the DataContext of your control to the TestViewModel instance. You can ensure this is done in design-mode only by using DesignerProperties.IsInDesignMode (DesignerProperties.IsInDesignTool for Silverlight):
public MyUserControl()
{
if (DesignerProperties.IsInDesignMode)
DataContext = new TestViewModel();
}

Here's how I achieve the goal. This does not work if you want to use an inherited data context in addition to the dependency properties.
Bind the control's data context to the control itself:
<UserControl ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
Use "normal" bindings in the control:
<UserControl ...>
<TextBlock Text="{Binding MyDependencyProperty}"/>
Add a design-time data context whose properties have the same names as the control's dependency properties:
<UserControl ...
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DataContext="{d:DesignInstance local:DesignTimeViewModel, IsDesignTimeCreatable=True}">
class DesignTimeViewModel
{
public string MyDependencyProperty { get; } = "The design-time value";
}
At runtime it will bind to the dependency properties, and at design-time it will bind to the DesignTimeViewModel properties.

Related

Understanding dependancy objects

I'm totally lost with dependancy objects and binding. I often get things working without understanding why and how, this question is about knowing what should be happening.
I have a tiny user control with the following XAML
<Grid>
<Image Source="{Binding Icon}"></Image>
<TextBlock Text="{Binding Title}"></TextBlock>
</Grid>
My code behind has the following
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(Image), typeof(MenuItem));
public Image Icon
{
get { return (Image)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(String), typeof(MenuItem));
public string Title
{
get { return (string)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
My MainWindow is empty, other than a reference to this control and to the ResourceDictionary. In the MainWindow code behind, I set the DataContext in the constructor.
<Window x:Class="AppUi.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:AppUi.Control"
Title="">
//set up to Resource Dictionary - all binding and styling works fine :)
<loc:MenuItem Icon="{Binding MailIcon}" Title="{Binding MailTitle}"></loc:MenuItem>
In the ModelView for the MainWindow, I have the following 2 properties
private Image_mailIcon;
public Image MailIcon{
//inotifyproperty implementation
}
private string _mailTitle;
public string MailTitle{
//inotifyproperty implementation
}
My question is, in the UserControl, how do I do the binding? Since it's a user control within a MainWindow, and the MainWindow already has a datacontext, I think the UserControl will inherit the DataContext from the parent (From what I have read).
So, in my UserControl XAML, should I be binding to the MainWindow's Code Behind properties OR to the ViewModel properties?
In other words, should my UserControl be
<Grid>
<Image Source="{Binding MailIcon}"></Image>
<TextBlock Text="{Binding MailTitle}"></TextBlock>
</Grid>
OR
<Grid>
<Image Source="{Binding Icon}"></Image>
<TextBlock Text="{Binding Title}"></TextBlock>
</Grid>
Or, because I'm using a DataContext and the UserControl inherits, do I even need the Dependancy Properties at all?
You normally don't want to overwrite DataContext passed through visual tree so you can use either ElementName or RelativeSource binding inside UserControl to change binding context. The easiest way to achive this is give UserControl some name and use it ElementName binding
<UserControl ... x:Name="myUserControl">
<!-- ... -->
<Grid>
<Image Source="{Binding Icon, ElementName=myUserControl}"/>
<TextBlock Text="{Binding Title, ElementName=myUserControl}"/>
</Grid>
<!-- ... -->
</UserControl>
This way binding is DataContext independent. You can also create UserControl with assumption it will always work with only specific type of DataContext and then you just use Path from that view model type but then DataContext of that UserControl must always be of the view model it's designed for (mostly inherited through visual tree)
<UserControl ...>
<!-- ... -->
<Grid>
<Image Source="{Binding MailIcon}"/>
<TextBlock Text="{Binding MailTitle}"/>
</Grid>
<!-- ... -->
</UserControl>
I would also change type of Icon property from Image to ImageSource for example. You already have Image control inside your UserControl and you just want to bind its Source
in the UserControl, how do I do the binding? ... the UserControl will inherit the DataContext from the parent
That is correct, the UserControl will inherit the DataContext from the parent Window. Therefore you can data bind from the UserControl directly to the parent Window.DataContext. Please note that you would bind to whatever object has been set as the DataContext, regardless of whether that was the code behind or a separate view model class.
However, you don't have to data bind to the parent's DataContext object in this situation... you have other options. You could data bind to your own UserControl DependencyPropertys using a RelativeSource Binding like this:
<TextBlock Text="{Binding Title, RelativeSource={RelativeSource
AncestorType={x:Type YourPrefix:YourUserControl}}}" />
You could also name your UserControl and reference its properties like this:
<TextBlock Text="{Binding Title, ElementName=YourUserControlName}" />
While this example seems to be more concise, don't overlook the first example, as RelativeSource is a useful and powerful friend to have.
should I be binding to the MainWindow's Code Behind properties OR to the ViewModel properties?
That's your choice... what do you want or need to data bind to? you just need to know that a direct data binding will use the auto set DataContext value, so if you don't want to use that, then you can just specify a different data source for the Binding as shown above.
Finally, regarding the need to use DependencyPropertys... you only need to declare them if you are developing a UserControl that needs to provide data binding abilities.

How can I set ComboBox DataContext in XAML?

I am trying to understand Binding so I have come up with a very simple program to try and test it.
I have the following element in my MainWindow:
<ComboBox Name="comboBox1" ItemsSource="{Binding}" />
In my Code I have the following observable collection:
public ObservableCollection<string> ComboItems = new ObservableCollection<string>();
I can successfully add items this way at any point during runtime:
comboBox1.DataContext = ComboItems;
ComboItems.Clea();
ComboItems.Add("Item");
My question is, how could I set the DataContext in XAML so that I don't have to do it in code? Is it possible?
Thank you!
Something common is:
<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
<ComboBox ItemsSource="{Binding ComboItems}" .../>
However usually you want to inject another object instance as DataContext, have a look at the MVVM pattern for example. Properties in WPF are inherited, so the ComboBox has the DataContext of the Window, it can be overwritten at any level though.
Note: For the Binding to work ComboItems needs to be a public property, not a field.
Resources of interest:
Data Binding Overview
Data Templating Overview
Depedency Properties Overview

MVVM way to use different controls for editing different objects

I need to design a form with a treeview in the left and a container for some other control in the remaining area. Whenever user selects an item in the treeview some custom control appears on the right. For example, let's say that the treeview contains values "Audio settings" and "Video settings", and I have two controls that can be bound to these settings and I want to display them on the form when needed.
Now, from what I've read about MVVM, I shouldn't have properties that will return UserControls or DataTemplates, am I right? It will be messing with "VM shouldn't know implementation details of the view" as I see it. So, how do I handle this situation properly in terms of MVVM? Should I maybe use converters for this and if so, how would it look?
I can't provide any code at the moment (mostly because there isn't any), but I will try to clarify the problem if needed.
Thanks in advance.
This is where the WPF templating system helps out.
The main idea is to have a ContentControl display the appropriate view depending on the selected value in the TreeView.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<ListBox DockPanel.Dock="Left" ItemsSource="{Binding Editors}" SelectedItem="{Binding SelectedEditor}" />
<ContentControl Content="{Binding SelectedEditor}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type l:VideoViewModel}">
<l:VideoView />
</DataTemplate>
<DataTemplate DataType="{x:Type l:AudioViewModel}">
<l:AudioView />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</Window>
AudioView and VideoView are UserControls.
As you can see, the ContentControl's content is bound to the SelectedEditor property in the ViewModel, which is also bound to the SelectedItem of the Listbox.
So the ViewModel for the main view looks like this.
public class MainWindowViewModel : INotifyPropertyChanged
{
public IEnumerable<object> Editors
{
get
{
yield return new VideoViewModel();
yield return new AudioViewModel();
}
}
private object selectedEditor;
public object SelectedEditor
{
get { return selectedEditor; }
set
{
if (selectedEditor == value)
return;
selectedEditor = value;
OnPropertyChanged("SelectedEditor");
}
}
}
So you can see that the main ViewModel has no GUI data in it.
To handle hooking up a TreeView to a SelectedItem property in a ViewModel see Data binding to SelectedItem in a WPF Treeview
You can implement it throw two properties: ShowAudioSettings and ShowVideoSettings in ViewModel and bind it on Visibility of your controls.
Also, you can make it with VisualStateManager.

WPF How to expose fields on a UserControl

I have a simple application with just a window and a user control. The user control has a list box. The user control is positioned on the Window and I want to bind the user control's listbox to an element on the window's data context.
The examples I've been able to find have CLR properties on the user control which are accessed in code not via XAML.
<Window x:Class="WpfApplication2b.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication2b="clr-namespace:WpfApplication2b" Title="MainWindow" Height="410" Width="520">
<Grid>
<WpfApplication2b:MyUserControl></WpfApplication2b:MyUserControl>
</Grid>
And here is the user control itself.
<UserControl x:Class="WpfApplication2b.MyUserControl"
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 Background="#FFD8AA13">
<ListBox Height="276" HorizontalAlignment="Left" Margin="12,12,0,0" Name="listBox1" VerticalAlignment="Top" Width="276" />
</Grid>
As you can see it's just a listbox on a different coloured background. I have no idea where to go next :)
I'm guessing that I need to add a code behind property for the list box as a dependency property?
Edit: I've added a dependencyProperty, but I don't think I've quite got the point.
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty ListBoxProperty;
static MyUserControl()
{
FrameworkPropertyMetadata md = new FrameworkPropertyMetadata();
MyUserControl.ListBoxProperty = DependencyProperty.Register("MyListBox", typeof (ListBox),
typeof (MyUserControl), md);
}
public ListBox MyListBox
{
get
{
return (ListBox) GetValue(ListBoxProperty);
}
set
{
SetValue(ListBoxProperty, value);
}
}
public MyUserControl()
{
InitializeComponent();
}
}
Your UserControl will inherit the DataContext from the Window so you can bind properties on the ListBox as though it were declared in the Window. To make the control more flexible you can declare Dependency Properties for the data items from the DataContext that you want to use (i.e. an ItemsSource collection) and pass them into the control, rather than passing the ListBox out.
I think this question/answer is almost what you're looking for. Essentially you're going to need to make a dependency property (using the AddOwner registration method) and set up the DataBinding on the ListBox's ItemsSource to hook to the Dependency Property. The example in the answer does the same thing for a ComboBox, and should be almost the same for a ListBox.
Exposing inner Control properties for binding in WPF

how to load wpf usercontrol in MVVM pattern

I'm creating a wpf user control which is in mvvm pattern.
So we have : view(with no code in codebehind file), viewmodel,model,dataaccess files.
I have MainWindow.xaml as a view file, which I need to bind with MainWindowModel.cs.
Usually, in a a wpf application we can do this with onStartUp event in App.xaml file. But in user control, as we do not have App.xaml...How do I achieve it ?
Please help :(...Thanks in Advance !!!
You can use a ContentControl, with a DataTemplate to bind the UserControl (View) to the ViewModel :
<DataTemplate DataType="{x:Type vm:MyViewModel}">
<v:MyUserControl />
</DataTemplate>
...
<ContentControl Content="{Binding Current}" />
WPF will pick the DataTemplate automatically based on the type of the Content
I know this is an old, answered question, but I have a different approach. I like to make implicit relationships in the App.xaml file:
<Application.Resources>
<DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
<Views:KioskView />
</DataTemplate>
</Application.Resources>
With this, there is no need to set a DataContext anywhere.
UPDATE >>>
In response to #Vignesh Natraj's request, here is a fuller explanation:
Once you have set up the DataTemplate in a Resources element, you can display the KioskView in this example by adding an instance of the KioskViewModel anywhere in your XAML. This could be filling the MainWindow, or just inside a particular section of the screen. You could also host multiple instances of the KioskViewModel in a ListBox and it will generate multiple KioskView instances.
You can add an instance of the KioskViewModel to your XAML in a couple of ways, depending on your requirements. One way is to declare the XML namespace for the project that contains the KioskViewModel.cs file and simply add an instance of it in a ContentControl to the page where you want your view to appear. For example, if you had a UserControl called MainView and the KioskViewModel.cs file was in a Kiosk.ViewModels namespace, you could use basic XAML like this:
<UserControl x:Class="Kiosk.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:Kiosk.ViewModels">
<UserControl.Resources>
<ViewModels:KioskViewModel x:Key="KioskViewModel" />
<DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
<Views:KioskView />
</DataTemplate>
</UserControl.Resources>
<ContentControl Content="{StaticResource KioskViewModel}" />
</UserControl>
I prefer to use the MVVM design pattern with WPF, so I would have a base view model class providing useful functionality such as implementing the essential INotifyPropertyChanged interface. I then have a property called ViewModel in the main (top level) view model of type BaseViewModel. This provides me with a nice way to change the ViewModel property to any view model that has derived from BaseViewModel and therefore to be able to change the associated view from the view model.
For example, in the MainViewModel.cs class that is bound to MainView there is a field and relating property:
private BaseViewModel viewModel = new KioskViewModel();
public BaseViewModel ViewModel
{
get { return viewModel; }
set { viewModel = value; NotifyPropertyChanged("ViewModel"); }
}
As you can see, it starts off as a KioskViewModel instance, but can be changed to any other view at any time in response to user interaction. For this setup, the XAML is very similar, but instead of declaring an instance of the view model in the Resources element, we bind to the property in the MainViewModel:
<UserControl x:Class="Kiosk.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:Kiosk.ViewModels">
<ContentControl Content="{Binding ViewModel}" />
</UserControl>
Note that for this example, we would need to declare two (or more to make this approach useful) DataTemplates in the App.xaml file:
<Application.Resources>
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
<Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
<Views:KioskView />
</DataTemplate>
</Application.Resources>
I've been using MVVM Light Toolkit which has a ViewModelLocator class that you can put properties to the viewmodels in. You then create a reference to the ViewModelLocator in your Mainwindow.xaml like so:
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True"/>
In the grid panel, or whatever you're using, you can then set the datacontext like this:
<Grid DataContext="{Binding MainWindowViewModel, Source={StaticResource Locator}}">
...
</Grid>
You could also go with MEFedMVVM which potentially adds a bit more flexibility in terms of being able to swap different viewModel implementations into the view.
The flexibility in both of these libraries is that you don't have to use their ViewModel base classes if you don't want to - the ViewModelLocator and the MEFedMVVM can work with any class.
There are endless ways to do it, wich all fall in one of the two categories:"view first" or "model first".
In a "view first" mode the view (e.g. your mainwindow) is created first and then (e.g. in the codebehind) the View instantiates the ViewModel and sets it as its datacontext):
private void WindowLoaded(object sender, EventArgs args)
{
this.DataContext = ViewModelService.GetViewModelX();
}
In a "model first" mode the ViewModel is there first and then instanciated the View.
// method of the viewmodel
public void LoadView()
{
// in this example the view abstracted using an interface
this.View = ViewService.GetViewX();
this.View.SetDataContext(this);
this.View.Show();
}
The examples given here are just one way of many. You could look at the various MVVM frameworks and see how they do it.
We can use ObjectDataProvider to call a method inside an object ..as follows :
<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
MethodName="ConvertTemp"
x:Key="convertTemp">
Is there anyway to do the same using DataTemplate
You can probably look at MSDN. I find it as a good resource, though it doesn't explain how to use usercontrols,you will find your way out.

Resources