MVVM View Binding - silverlight

Lets say I have a list of items. So I have 2 views: ListView and ItemView.
I also have 2 ViewModels: ListViewModel and ItemViewModel.
In ListViewModel I create and initialize ObservableCollection of ItemViewModels.
In ListView I have ListBox with ItemTemplate -> ItemView, and ItemSource binded to the ObservableCoolection into the ListViewModel.
I want to bind each ItemView to each ItemViewModel so I will be able to use the binding into ItemView.xaml, but I cannot achive it.

What I understood from your question is you want to bind ItemViewModel to ItemView.xaml and your ListBox resides in some other xaml(say ListBox.xaml). You don't want to apply binding related to ItemViewmodel and ItemVIew in ListBox.xaml. If this was the issue, you
can easily create a DataTemplate mapping to achieve so:
<Window
xmlns:vw="namespace of your view files (i.e. xaml files. ListBox.xaml and ItemView.xaml)"
xmlns:ViewModels="namespace of your view model files (i.e. ItemViewModel.cs, ListBoxViewModel.cs)">
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModels:ItemViewModel}">
<vw:ItemView />
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Path=List of ItemViewmodel in ListBoxViewModel.cs}"
</Grid>
</Window>
Then, you ItemViewModel class will be mapped with ItemView as it is specified in Resources without any key. Now you can apply binding in ItemView.xaml. Look, you do not need to assign Itemtemplate of ListBox here, that will be resolved automatically. If you want to specify the ItemTemplate anyway (and do not want to specify in resource), then write this:
<ListBox.ItemTemplate>
<DataTemplate>
<vw:ItemView />
</DataTemplate>
</ListBox.ItemTemplate>
Either way should work :)

Related

WP7 XAML Bind to property in parent

I'm writting an app in WP7 (Silverlight 3). I have a view model that looks like this
public class MainViewModel
{
public List<ActivityTypes> ActivityTypes{get;set;}
public RelayCommand LoadActivity{get;set;}
}
My pages datacontext is set to the view model and I have a listbox with it's item source set to the ActivityTypes collection. In the listbox I'm trying to render a list of buttons who's command is bound to the LoadActivity property on the viewmodel. RelayCommand is part of the MVVM Light toolkit in case you are wondering what it is.
The problem I am having is I can't find a way to bind my button command to the LoadActivity property as my listbox has it's itemsource set to the Activitytypes collection and this property is in the parent. I've read about FindAncester but it doesn't look like this is supported in Silverlight 3.
My XAML looks like this
<UserControl.Resources>
<DataTemplate x:Key="ActivityTypeListTemplate">
<StackPanel>
<Button Command="{Binding LoadActivity}"> <!--binding not found as we're in the collection-->
<TextBlock Text="{Binding Name}" FontSize="50"/>
</Button>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<ListBox Margin="0" ItemsSource="{Binding ActivityTypes}" ItemTemplate="{StaticResource ActivityTypeListTemplate}"/>
</Grid>
What's the best way to code something like this?
There is no "direct" way to do this. You can set the Buttons DataContext to your MainViewModel (preferably as a StaticResource link) and the it would work.
Take a look at Bind to parent object in xaml

Binding the ViewModel itself inside a DataTemplate with Caliburn Micro Conventions

I'm a newcomer to Caliburn.Micro and there are a few things I'm still not getting.
ViewModel first:
First of is a ViewModel that manages a Collection of other ViewModels:
public class NavigationBarViewModel : PropertyChangedBase
{
public BindableCollection<IHaveDisplayName> Items { get; set; }
}
I've got a ItemsControl (it's Telerik RadOutlookBar if that matters) as the root of a UserControl
of that view and I set the ItemTemplate too ensure that the ViewModels I insert into the collection are wrapped in a corresponding RadOutlookBarItem ( should I use ItemContainer instead of ItemTemplate here? ).
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=DisplayName}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<telerik:RadOutlookBarItem cal:Bind.Model="{Binding}"
Header="{Binding Path=DisplayName}">
<ContentControl />
</telerik:RadOutlookBarItem>
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>
This way I wan't the ViewModels in the collection to appear where the ContentControl is. I Bind the model to the root item of the DataTemplate to ensure conventions will work but have no idea how to bind to the ContentControl with convention. The DataContext inside the DataTemplate is of course the ViewModel itself. Using normal WPF standard I would put Content="{Binding}".
Now the model is there inside the RadOutlookBarItem but it's view doesn't get applied. Not even View can't be found, only a string with the class name.
Isn't this the proper way to do this?
As I answered here: Dynamic Telerik RadOutlookBar headers come out wrong with ItemTemplate in which I thought was a unrelated matter I was using the wrong property. ItemTemplate controls the picker and contentTemplate what comes up when you select. Here is the code that works:
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.ContentTemplate>
<DataTemplate >
<ContentControl cal:View.Model="{Binding}" />
</DataTemplate>
</telerik:RadOutlookBar.ContentTemplate>
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<TextBlock x:Name="DisplayName"
cal:Bind.Model="{Binding}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="DisplayName"
cal:Bind.Model="{Binding}" />
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>

View Model, Dependency Properties Confusion

I am developing a custom WPF control and confused how to use the dependency property. My view model contains 2 properties:
class Customer {
string Name;
string ID;
}
My custom control is responsible for displaying these fields.
Q1: Do I need to define any dependency properties (eg "Name", "ID") in my custom control?
Q2: I am using ItemsControl to display a list of Customers. How is the Customer object passed to my custom control? Is it done through the DataContext or do I need to add a "Customer" dependency property in my control and in the xaml, bind "Customer" to "something" (what's that something)?
<ItemPresenter>
<MyCustomControl Customer="??what should i put here???"/>
</ItemPresender>
Q1. Why do you have a custom control? Ordinarily, you would just create a UserControl (there is a distinction in WPF between UserControl and custom control) and bind properties within your UserControl to properties of your view model. For example (let's call this CustomerView):
<UserControl ...>
<StackPanel>
<TextBlock Text="{Binding ID}"/>
<TextBox Text="{Binding Name}"/>
</StackPanel>
</UserControl>
Q2. Through the DataContext. For example, you might have something like this:
<ItemsControl ItemsSource="{Binding Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CustomerView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Each item generated by the ItemsControl will have the related data item set as its DataContext. Hence, each CustomerView will have the appropriate Customer as its DataContext.

Switch View based on selected TreeViewItem

I have a Shell.xaml file which contains two other UserControls. On the left is my TreeView and on the right is a detail screen.
I want the detailscreen to be switchable based on a selected TreeViewItem. I know this can be achieved by using DataTemplates, because I've done it with simple button clicks and using the <ContentControl Content="{Binding CurrentDetailViewModel}"> tag to accomplish this, but I have no idea how to accomplish this based on a selected TreeViewItem. I also have a separate ViewModel class for my UserControl which holds my TreeView and a separate for each detail screen.
I've been using Josh Smith's tutorial on TreeViews: http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
So I also do use the TreeViewItemViewModel.cs class of his.
Could someone shed some light onto this?
Thanks,
Grant
If both the treeview and the details are displaying the same object (i.e the ItemsSource of the treeview contains the objects that you want to data template in the custom control) then you should be able to set a property on an underlying ViewModel that both controls share and have the custom control display something relevant with data templates.
for example, in the ViewModel:
object TreeViewSelectedItem
{
get{ return _treeViewSelectedItem;}
set {_treeViewSelectedItem = value; NotifyPropertyChanged("TreeViewSelectedItem");}
}
Treeview xaml
<TreeView ... SelectedItem={Binding TreeViewSelectedItem Mode=OneWayToSource}".../>
custom control xaml
<UserControl>
<Control.Resources>
<DataTemplate DataType="{x:Type Plane}">
....
</DataTemplate>
<DataTemplate DataType="{x:Type Train}">
....
</DataTemplate>
<DataTemplate DataType="{x:Type Automobile}">
....
</DataTemplate>
</Control.Resources>
<ContentControl Content={Binding TreeViewSelectedItem}"/>
</Usercontrol>

Is it possible to Bind the DataContext of a UserControl to a property

I have a user control that I would like to use in two different contexts. The user control needs its DataContext set to an instance of an appropriate ViewModel that has been created by the parent view/viewmodel.
I was hoping for something like:
<local:Child DataContext="{Binding ChildViewModel}"/>
where ChildViewModel is a inpc-styled property of the ViewModel that the page is bound to.
That doesn't seem to work. Is it possible to assign the DataContext by using Binding?
It would probably be simpler to bind the Content of an ContentControl to your child ViewModel like this:
<ContentControl Content="{Binding ChildViewModel}" />
..and then have a DataTemplate to apply your local:Child View, like this
<DataTemplate DataType="{x:Type local:ChildViewModel}">
<local:Child />
</DataTemplate>

Resources