How can I easily expose bindable properties of nested controls from a custom UserControl? - silverlight

My first question here on the Stack. Forgive me for the bad explanation in advance.
I am working on my first MVVM application (Silverlight). I have a custom user control that contains a ListBox to show navigation items. This control is placed in my main xaml page. I don't know if I need to create a composite view model (my main page view model) with a view model especially for the custom control in it or if there is some way to elevate the ListBox properties that I need to bind to.
Through XAML I don't know how to bind, let's say, the ItemsSource property of the ListBox inside the custom control to my main page viewmodel. Basically, I'm at the point that I am questioning my design decision for trying to bind the custom control through my main page view model.
What I have done so far is create dependency properties for the custom control and try to tunnel those dependency properties down to the ListBox properties. I've achieved success with this method for ItemsSource but am having issues with SelectedItem.
Even if I do get SelectedItem to work, it still feels Wrong. Thanks for any advice in advance.

The UserControl should inherit the DataContext from its parent control, unless you are setting it directly. You can then bind to the properties on your view model from your UserControl.
If you would like to create a ViewModel specifically for the UserControl, you can also do that. You would then expose it as a property on your main ViewModel, and bind to it in the MainPage. Example:
public class MainViewModel
{
public ChildViewModel ChildInfo { get; private set; }
}
And then in the view:
<Grid>
...
<lcl:ChildView DataContext="{Binding ChildInfo}" />
...
</Grid>
Your ChildViewModel would then contain properties like SelectedItem to bind your ListBox to.

Related

MVVM - Menu View with Preview View (Shared ViewModel) approach

I've just started my journey with MVVM and WPF and I need an advice to solve my problem or rather guide me towards right solution.
Link to image: https://s12.postimg.org/md0h6fv3x/Simple_App.png
Description (what I want to achieve):
View A is a menu (UserControl) with ListBox and DataContext: V.ObservableCollection
View B is a preview to selected item from View A ListBox
View A & B are loaded from MainWindow
What is simpliest and cleanest approach to achieve that?
I was thinking about sharing the same ViewModel with View A&B.
Create a SelectedItem property in ViewModel and then put it MainWindow's resources and bind datacontext to View A & B
Is it valid approach? Will that VM be updated properly in both views if it get changed?
Somehow bind View's A listbox SelectedItem to View B preview mode but don't know how.
Use only one ViewModel.
Eg; Pseudo code :
public class ViewModel : INotifyPropertyChanged
{
public ObservableCollection<Employee>{get;}
/* provide change notification in ChosenItem */
public Employee ChosenItem{get;set;}
}
Use this ViewModel as DataContext for both Views.

How do I bind wpf with specific datacontext from different classes?

Hi guys I am very new to WPF. I have two datacontexts in two different classes which are being binded by the elements in the View producing datatriggers, and one or the other wouldn't work as they cannot bind both datacontexts together. How do I bind xaml from two different classes using datacontext? Is there any alternative way could make it easier?
Class A
public Window1()
{
InitializeComponent();
Appointments = new Appointments();
DataContext = Appointments;
}
Class B
private void FilterAppointments()
{
this.DataContext = this;
...
Firstly, you should never use DataContext = this; in any UserControl in a serious WPF Application. Secondly, you should look up the MVVM design pattern, which provides the idea of a view model for each view. Your Window or UserControl are the 'Views' and your view models are simply classes that contain all of the data properties that you need to display in your view.
Therefore, you should declare a view model class (that implements the INotifyPropertyChanged interface) and put whatever you wanted to data bind into that. Finally, you should set that object as the DataContext property value. In that way, you'll have access to all the data that you need.
Looking again at your question, it just occurred to me that you may have set the DataContext to this so that you could use properties that you declared in your Window or UserControl. If this is the case, then you should not set the DataContext to this, instead using a RelativeSource Binding to access the properties. That would free up the actual DataContext to be set however you like. Try this Binding within the Window or UserControl:
<TextBlock Text="{Binding PropertyName, RelativeSource={RelativeSource
AncestorType={x:Type YourPrefix:YourWindowOrControl}}}" />

Retrieves value from Wpf UserControlLibrary to WpfForm

In my WPF application, I have a usercontrol library. In this library, I have a listview control along with textbox and button controls.
I have placed this usercontrol in a WPF window form. How can I retrieve the listviewitems of my usercontrol in this WPF window form?
You ask a very general question. There are dozens of ways to do that, depends on your needs. For example: when you place you UserControl within the Window - you should name it (e.g. . Then, within the UserControl, you can have a public function, or a public getter, which will return the items (it is the 'Items' property of the ListView).
Another way is binding. If you have a ViewModel, or any other class as the DataContext, you can bind the ItemsSource of the ListView to a collection on your ViewModel. Unless you change the DataContext of the UserControl - it will have the same DataContext as the main Window.

Custom control, View Model and dependency properties

I'm creating custom control and because I need to do lot's of binding inside a style/template it makes perfect sense to go with MVVM. Where do I declare dependency properties then?
Do they stay in control class? How do I link them to VM?
See my answer to your other question about custom controls and view models. Here's the short version:
Custom controls shouldn't have view models.Don't set the data context of your own control. That's reserved for the consumer.All of your dependency properties should be declared in your MyCustomControl.cs file.Use TemplateBinding in your genric.xaml because it's more efficient that Binding.
To put it another way, what's the view model for a Border or a Button? Answer: they don't have one because they're just controls. UserControls have view models, but controls just present and interact with the data which you give them (where? In your UserControl). Custom control development is probably the hardest thing for a seasoned MVVM developer: your reflex is to make a view model, but that reflex is unfortunately wrong. I know because I've made this mistake myself.
Dependency Properties could be delared in the Control they are belongs to.
When following MVVM in WPF/Silverlight the common approach is to set ViewModel as DataContext of the appropriate View. So you would be able to link custom Dependency Properties to the ViewModel properties using Bindings in XAML.
Let's assume you already set ViewMosel to DataContext of the View:
var view = new UserView
{
DataContext = new UserViewModel { Name = "Custom Name" }
};
public class UserViewModel
{
string Name { get; set; }
}
UserView.xaml:
<TextBlock Text="{Binding Name}" />
When creating a custom control, the control itself is a view model. Declare dependency properties on it to expose bindings that users of the custom control can leverage. For example if you have a timeline control, you might have properties like StartDate and EndDate on the control exposed as dependency properties. Your Controls Default Template would make template bindings to the dependency properties. A consumer of your control might then have a project timeline viewmodel that he binds to the properties on the control.
The primary purpose of a custom control is to provide behavior and a default look and feel for that behavior which is easy to override (by providing a new template). Hope this helps.

WPF Binding Between Controls

I have a control on a page that contains a listbox. I also have another control which is a detail view.
Both of the controls have their own ViewModel which their child controls bind to.
Image Outlook. It has a list of folders and when you select a folder the detail control displays the contents of the folder.
How can I bind the detail control to the selected item in the list control?
If I got it correctly, you have master-detail situation. Can you add list of details ViewModel as property of master ViewModel? That way you don't need anything special. It should work automatically. Something like this:
public class MyMasterViewModel
{
public List<MyDetailViewModel> Details
{ get; set; }
}
Set collection of MyMasterViewModel as DataContext to both views and configure binding appropriately. As you move through master list, detail list will be automatically updated.
You'll probably need to set IsSynchronizedWithCurrentItem property:
<ListBox ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
DisplayMemberPath="Something"/>
Use element-to-element binding, here as link to MSDN page http://msdn.microsoft.com/en-us/library/ms752347.aspx with master-detail example.

Resources