Here is the XAML:
<ListBox ItemsSource="{Binding Documents}" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
<TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
Ok so the ListBox's ItemSource is bound to the Documents collection in the VM and properly renders the Titles and IDs
The Context Menu's ItemSource is bound to the CategoryList collection in the VM and properly renders the list of categories.
The problem I have is with the Command Binding:
Command="{Binding AddDocumentToCategoryContextMenuCommand}"
Since the ItemSource for the ContextMenu is already set, it tries to get the AddDocumentToCategoryContextMenuCommand from CategoryList. Obviously the command is not there, it is a member of the VM.
I do not want any references to the VMs or Models in the XAML. Everything is constructed using Unity and VM-View is associated in App.xaml:
<Application.Resources>
<DataTemplate DataType="{x:Type vms:FeedViewModel}">
<views:FeedView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:DocumentsViewModel}">
<views:DocumentsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ManagementViewModel}">
<views:ManagementView/>
</DataTemplate>
<DataTemplate DataType="{x:Type dev:DevelopmentViewModel}">
<dev:DevelopmentView />
</DataTemplate>
</Application.Resources>
How can I databind to a member of the VM from within the ContextItem.
Thanks.
UPDATED edit #1 starts Here
Here is the updated xaml (but still not working but some insight gained):
<ListBox ItemsSource="{Binding Documents}" x:Name="Results" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
<TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding ElementName=Results, Path=DataContext.AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
I have this example working for a simple example that does not use a ContextMenu. It appears that the ContextMenu (even though attached to the ListBox) is not part of the user control visual tree. The binding always comes back null / not found. I think the ContextMenu, because it is a floating "window" is constructed in its own tree and therefore cannot find the ListBox call "Results" in order to access the ListBox's DataContext.
Any thoughts on this? Any recommendations on how deal with?
Edit #2 Starts Here
In case you are are wondering, figured out the answer to the binding question:
This binding works:
Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}
Hope this helps others with the same question.
One last update for completeness.
In order for the command to know which context menu item was clicked on, I had to change the xaml slightly (silly oversight):
<ListBox.ContextMenu>
<ContextMenu x:Name="Context" ItemsSource="{Binding CategoryList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}"
CommandParameter="{Binding Category.ID}"
Header="{Binding Category.Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ListBox.ContextMenu>
Again, hope this helps others.
Use the ElementName property of the binding to specify that. You'd end up with something like this:
Command="{Binding ElementName=ViewModelObject
Path=AddDocumentToCategoryContextMenuCommand}"
Related
I have a GridView that's bound to a Dictionary:
<GridView x:Uid="SearchInputRecentSearches"
x:Name="SearchInputRecentSearches"
ItemsSource="{Binding RecentSearches}"
Grid.Row="1"
Grid.Column="1"
Style="{StaticResource RecentSearchGrid}">
Inside of this GridView, in the ItemTemplate, I want to show the Key or Value:
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Style="{StaticResource RecentSearchesItemStackPanel}">
<TextBlock Text="{Binding Key}"/>
<Button Width="31"
Height="31"
Command="{Binding DataContext.ExecuteDeleteSearch, ElementName=SearchInputRecentSearches}"
CommandParameter="{Binding Key}"
Template="{StaticResource DeleteButton}"/>
<TextBlock Style="{StaticResource RecentSearchStyle}"
Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
However, nothing displays for either Key or Value when I run this. I've tried referring to Path=Key and Path=Value inside of the binding, but this doesn't work, either. I'm currently using a ValueConverter to get the key or value out, but this seems a little unnecessary and I was hoping someone could point out what I was doing wrong!
I have a list of users on my viewmodel that I pass to the following listView:
<ListView
Background="Azure"
x:Name="ContactList"
ItemsSource="{Binding Path=User}"
SelectedItem="{Binding SelectedUser, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Border Width="300" Height="Auto" BorderThickness="1">
<StackPanel>
<TextBlock>
<Run Text="{Binding Name}" />
<Run Text="{Binding Age}" />
</TextBlock>
<CheckBox Visibility="{???}">
<TextBlock FlowDirection="LeftToRight"></TextBlock>
</CheckBox>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As you can see my DataTemplate contains a checkbox. I would like its Visibility to depend on a bool-property I have on my ViewModel. How can I access this property from within the listView?
From looking around here it seems like there are ways to access the ListView-items parent. I think that would do it for me. Can someone point me in the right direction . Thanks
The best way to do this is to include the visibility setting along with your user data. Assuming your view model visibility property is named CheckBoxVisibility, you would have something like this:
<ListView ItemsSource="{Binding}" ...>
<ListView.ItemTemplate>
<DataTemplate>
...
<Run Text="{Binding Path=User.Name}" />
<Run Text="{Binding Path=User.Age}" />
...
<CheckBox Visibility="{Binding Path=CheckBoxVisibility}">
...
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In WPF, you can use a RelativeSource=RelativeAncestor binding; however, this is not available in Window Store/Windows Phone 8+ apps.
I have troubles with binding data to a Listbox to dynamically create ExpanderView.
I have used Listboxes in my Code before, so I'm not sure if the binding is really the problem. Am I setting the contents of ExpanderView wrong?
My Code so far in XAML:
<ListBox x:Name="Newsticker_Listbox">
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}" ItemsSource="{Binding}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"
ItemTemplate="{StaticResource CustomItemTemplate}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
the Templates:
<!--newsfeed templates-->
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="CustomHeaderTemplate">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
<DataTemplate x:Key="CustomExpanderTemplate">
<Image Source="{Binding Subtitle}" />
</DataTemplate>
<DataTemplate x:Key="CustomItemTemplate">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I'm binding with
ObservableCollection<news> newslist = new ObservableCollection<news>();
//populate
Newsticker_Listbox.ItemsSource = newslist;
news is a really simple object, it just stores some strings, which can be read out by news.Title, news.Subtitle etc
I've used the example from http://www.geekchamp.com/articles/expand-and-collapse-expanderview-inside-data-bound-listbox-via-code as basic for my code, I've just simplified it for my cause (mabye too much?)
Help is very appreciated, thank you all in advance
EDIT
This code works so far, but why does the solution with templates not work?
<ListBox x:Name="Newsticker_Listbox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
<toolkit:ExpanderView>
<toolkit:ExpanderView.Header>
<TextBlock Text="{Binding Titel}" />
</toolkit:ExpanderView.Header>
<toolkit:ExpanderView.Expander>
<TextBlock Text="{Binding Untertitel}" />
</toolkit:ExpanderView.Expander>
<toolkit:ExpanderView.Items>
<TextBlock Text="{Binding Text}" />
</toolkit:ExpanderView.Items>
</toolkit:ExpanderView>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Remove your Header={Binding} and Expander={Binding} XAML code. It is overriding your custom HeaderTemplate and ExpanderTemplate.
You bound the Header and the Expander to the context of the application, which it doesn't really understand, so the binding resolved itself to nothing, so your ExpanderView displays nothing.
I have a WPF application using MVVM.
This code is from my ResourceDictionary.xaml
<DataTemplate x:Key="LogListTemplate">
<ListBox ItemsSource="{Binding LogList, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource HorizontalListBoxItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource ErrorBorders}">
<StackPanel ToolTip="{Binding Details}" Width="250">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}" TextWrapping="Wrap" />
<Button Command="{Binding AddToTempDtdFileCommand}" CommandParameter="{Binding Details}" Content="Ignore" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
When I click on Button, the command does not execute. Testing confirms this is because my Button lives within a ListBox.
My problem is I can't move my button out of the ListBox for 2 reasons.
1. Asthetics/UI (the button has belong with the information)
2. Binding to the LogList is done from within the ListBox.ItemTemplate
Does any one have any suggestions?
If the command is defined in the ViewModel you can reach it by using RelativeSource. RelativeSource can find an ancestor (which is your View) so you can use its DataContext (your ViewModel).
<Button Command="{Binding DataContext.AddToTempDtdFileCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type YourViewClass}}}" CommandParameter="{Binding Details}" Content="Ignore" />
Suppose I have a user control which datacontext is bound to a VM. This VM has a property for a list MyList.
Inside this user control I have a ComboBox, I want to set following kind of xaml
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Stretch">
<sdk:DataGrid ItemsSource="{Binding YourList}" IsReadOnly="True" AutoGenerateColumns="False" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<!-- ...... -->
<sdk:DataGridTemplateColumn Header="User" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.MyList}" DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding UserID}" ></ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</StackPanel>
</Grid>
but it is not working.
How to resolve this problem?
This worked form me. This was the ItemSource for a ComboBox that was within a DataGrid:
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=sdk:DataGrid},
Path=DataContext.Teams}">
Are you trying to get to the main VM from within the UserControl? take a look at this solution. http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx