Silverlight Treeview SelectedItem TwoWay binding causing error in blend - silverlight

I have a Treeview in a Silverlight 4 project, and I want to bind to its SelectedItem. When I do a binding to SelectedItem (Mode=TwoWay) its throwing an error in blend because SelectedItem is readonly, which is causing my XAML to not render. I don't ever want to SET the SelectedItem property, I just want to know when it changes via UI interaction. In WPF, I would just bind its SelectedItem using Mode=OneWayToSource, but Silverlight does not support that mode (afaik).
Treeview :
<controls:TreeView ItemsSource="{Binding Repository.MajorClasses}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
Is there a workaround that anyone has used? And anyone know why OneWayToSource is omitted from Silverlight?

It's really readonly, so you cann't do that. You can use TreeView as base control and create CustomTreeView with implementation of bindable SelectedItem. Or create own behavior(attached property). Or use some third party control (f.i. telerik).

If you just want your VM to be informed when the user changes the selection, you should be able to do exactly what you are doing (a two way binding).
I have this working in Visual studio so, I suggest trying it from there, might just be a problem with Blend. VS intellisense doesn't suggest SelectedItem when typing in the XAML editor but that doesn't stop it from working.
The bound property in your VM is definately of the right type (MajorClass by the looks of it)?

What you need to do is make use of an Interaction Trigger and bind it to the SelectedItemChangedevent as follows:
<sdk:TreeView x:Name="ModuleNavigationItemWrappersTreeView" ItemsSource="{Binding ModuleNavigationItemWrappers}">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<Image Source="/VanguardFinancials.Common;component/Images/icons/flag_blue.png" />
<TextBlock Margin="2,0,0,0" Text="{Binding ItemDescription}"></TextBlock>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="SelectedItemChanged">
<interactivity:InvokeCommandAction Command="{Binding TrackSelectedModuleNavigationItemWrapper}" CommandParameter="{Binding ElementName=ModuleNavigationItemWrappersTreeView}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</sdk:TreeView>
Visit this for more information about Behaviors and Triggers. Hope this helps.

Related

Binding a button nested in DataTemplate

I need to bind a button's command inside a datatemplate like below:
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="-" Cursor="Hand" Width="50"
Background="Red" x:Name="removeButton"
Command="{Binding Remove}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
Unfortunately it does not work. How can I bind a command in a button insade a datatemplate?
I found that thread in the forum:
Bindings in nested WPF DataTemplates
but the method given by person, who answered this question, does not work as well. I think, that something has changed in WPF since this time, I would you grateful for your help.
If Remove is defined in the view model of the parent ListView, you could bind to it using a RelativeSource:
Command="{Binding DataContext.Remove,
RelativeSource={RelativeSource AncestorType=ListView}}"
You could also set the AncestorType to Window or UserControl depending on where the command property is defined and where the DataTemplate is applied.

CheckedListBox in WPF

We are working on an application using the MVVM architectural style (WPF) and facing an issue.
Before using WPF we have worked with WinForms and we used CheckedListBox. But now we are unable to find such control in WPF.
We are also using Infragistic toolkit.
Please provide any kind of help. Any lead will be appreciable.
You can take a Listbox and give it a Template with a Checkbox in.
Something like:
<ListBox ItemsSource="{Binding MyItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This looks like this:
Edit: The Items must have a Property "IsSelected" or you have to Wrap them in a SelectableItem helper class, which holds the original Item and a IsSelected Property.

DataGrid binding in DataTemplate

I'm currently trying to do some binding inside of a datagrid but I'm having problems getting up to the level of DataContext of the view.
Here is the code:
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding Operators}"
ItemsSource="{Binding DataContext.OperatorList,ElementName=FilterGrid}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
Any ideas on whats wrong? The View's Viewmodel is connected in the code behind.
EDIT: The Binding that is not working is the ItemsSource binding shown above
When you use the DataTemplate of the DataGrid, you cannot use ElementName bindings as it won't resolve properly due to limitations in the resolution capabilities of FindControl within the DataGrid control hierarchy. You need to use a RelativeSource binding that travels up the control tree looking for a specific control type (which you need to determine - from your element name I assumed it was a DataGrid ancestor type).
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox
SelectedItem="{Binding Operators}"
ItemsSource="{Binding DataContext.OperatorList,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
See this SO post that shares some potentially related sample code using MVVM to access the DataContext of the UserControl host to populate a ComboBox ItemsSource.

WPF XAML Binding

Hello
I have a problem with a binding that I want to do and can't find any information on how to do it.
Basically I want to bind an object to a property of another object.
For example
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
This is kind of weird but it would help on the code that i'm implementing, so on a property of one object I want to have another object bind in xaml.
I don't know if this is possible, any pointers would be helpful
Thanks, Ruben
That is how you do it; you just need to specify the Path.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are wanting the DataContext of the TextBox; then your Path would change accordingly.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=DataContext}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are needing to use the Tag property within a WPF application you might want to re-evaluate your approach as I have yet to use the Tag property since moving from WinForms as that need has been replaced by leveraging the data binding functionality within WPF.
UPDATE:
If your goal is to bind to a given control versus a property on the control; then don't specify the property name within the Path.
Based on your goal; attached behaviors would be a better approach and allow you to wrap the functionality within the extended DataGrid.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2,Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
Assuming you want the value of the Text property of TxtBx1 to be the value of the Text property in TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="{Binding ElementName=TxtBx2, Path=Text}" />
<TextBox x:Name="TxtBx2" Text="test" />
Update
Assuming (possibly incorrectly again!) that you want to bind the TxtBx1 element to the Tag of TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="test" />
<TextBox x:Name="TxtBx2" Tag="{Binding ElementName=TxtBx1}" Text="test" />
Just out of interest, why do you want to do such a thing?
Update 2
Assuming that you have a Datagrid that you've extended from the wpftoolkit datagrid and a user control that is a pager for that Datagrid, and when you move to another page you need to do some processing on the datagrid, then why don't you just either update the datagrid in your page change event (if using code behind), or update the items that the datagrid is bound to in your page change verb on your view model (if using MVVM)?
Well, it does make sense to bind to an entire object(not to any specific property) with items control such as this:
<ListBox x:Name="pictureBox"
ItemsSource=”{Binding Source={StaticResource photos}}" …>
......
</ListBox>

Silverlight Binding

I've a Silverlight page using a MVVM behind it to handle all the data bits going on.
The data context is set for the page using:
DataContext="{Binding AddNewClientViewModel, Source={StaticResource ServiceLocator}}"
ServiceLocator being a service that allows me to create and inject the appropriate VM using an IoC container.
This all works fine.
Now I have a DataForm like so:
<df:DataForm CurrentItem="{Binding NewClient}" AutoGenerateFields="False" >
<df:DataForm.NewItemTemplate>
<DataTemplate>
<StackPanel>
<df:DataField>
<TextBox Text="{Binding ClientName}" />
</df:DataField>
<df:DataField>
<TextBox Text="{Binding Property_on_the_VM_not_on_NewClient}" />
</df:DataField>
</StackPanel>
</DataTemplate>
</df:DataForm.NewItemTemplate>
</df:DataForm>
OK, so this dataform binds to the NewClient property on my ViewModel. The first DataField binds to the NewClient.ClientName. The second DataField I'd like to bind to a property that hangs of the root ViewModel.
I know there is the 'Source' parameter that you can pass in when binding, if I had a static resource of the VM or similar I could point it to that, but I don't. How can I link this binding up with property on the parent VM?
Edit
After a post by Jobi below, I've tried the following:
<TextBox DataContext="{Binding DataContext, ElementName=root}" Text="{Binding MyProperty}" />
And my top level control:
x:Name="root"
DataContext="{Binding AddNewClientViewModel, Source={StaticResource ServiceLocator}}"
No dice with getting this to work...
What you need is a DataContextProxy which was created by Dan Wahlin. The problem is that once you get into the data form, you have a new data context. There is no easy way to reach back up to the view's data context. The data context proxy allows you to easily do this and I've used it quite a bit found it works great.
On the second TextBox you can do an ElementName binding to the root element where the Parent VM has already DataContext to.
<TextBox DataContent="{Binding DataContext, ElementName=rootLevelControl}" Text="{Binding property}"

Resources