Bind to parent control from within context menu within data template - wpf

I'm wanting to bind to a parent control from a context menu within a datatemplate.
Unfortunately I'm restricted to .net 3.5 and can't use the x:reference extension introduced in .net 4.
Below is an example of what I'm trying to do
<Window x:Class="WpfApplication17.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication17"
Name="window">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<Rectangle Width="100" Height="100" Fill="Red">
<Rectangle.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Colour}"/>
<MenuItem Header="{Binding ElementName=window, Path=ActualWidth}"/>
</ContextMenu>
</Rectangle.ContextMenu>
</Rectangle>
</DataTemplate>
</Window.Resources>
</Window>
But I get "Cannot find source for binding with reference 'ElementName=window'" error due to the context menu not being part of the visual tree.
Edit :
That works great! .. however, it doesn't seem to work when I use a composite collection such as the following
<Window.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<Rectangle Width="100" Height="100" Fill="Red"
Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
<Rectangle.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<MenuItem Header="{Binding Colour}"/>
<MenuItem Header="{Binding Path=PlacementTarget.Tag.ActualWidth, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
<!--<ContextMenu>
<MenuItem Header="{Binding Colour}"/>
<MenuItem Header="{Binding Path=PlacementTarget.Tag.ActualWidth, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>-->
</Rectangle.ContextMenu>
</Rectangle>
</DataTemplate>
</Window.Resources>

Please try this:
<DataTemplate DataType="{x:Type local:Car}">
<Rectangle Width="100" Height="100" Fill="Red"
Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
<Rectangle.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Colour}"/>
<MenuItem Header="{Binding Path=PlacementTarget.Tag.ActualWidth, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</Rectangle.ContextMenu>
</Rectangle>
</DataTemplate>
See my answer here too.

Related

i need to bind the context menu with the tag , but this code didnt work for me

i need to bind the context menu with the tag , but this code didnt work for me.
<TextBox Width="100" Name="dd" Tag="jatin" Height="50" Text="{Binding Tag, RelativeSource={RelativeSource Self}}">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="harsh"></MenuItem>
<MenuItem Header="jatin"></MenuItem>
<MenuItem Header="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Grid},FallbackValue=BindingFailed}"></MenuItem>
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</Grid>
Try this,
<MenuItem Header="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />

How to modify Avalon 2.0 startup layout WPF

I have downloaded the avalon 2.0 and on load the tool panel starts on the right and the files panel starts on the left.
I am trying to get the tool panel to dock on the left on load even when I have deleted everything that is related to FileViewModel which loads on the left a blank panel stays on the left.
This image below shows how the window currently loads:
I want to have the tool panel loads on the left like this:(I achieved this by dragging the tool pane on run time.
In my WPF I can only see one LayoutAnchorablePane so I can't see why the screen is split into two?
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Menu Grid.Row="0">
<MenuItem Header="File">
<MenuItem Header="New" Command="{Binding NewCommand}"/>
<MenuItem Header="Open" Command="{Binding OpenCommand}"/>
<Separator/>
<MenuItem Header="Save" Command="{Binding ActiveDocument.SaveCommand}"/>
<MenuItem Header="Save As..." Command="{Binding ActiveDocument.SaveAsCommand}"/>
<Separator/>
<MenuItem Header="Close" Command="{Binding ActiveDocument.CloseCommand}"/>
</MenuItem>
<MenuItem Header="Tools">
<MenuItem Header="{Binding FileStats.Title, Mode=TwoWay}" IsChecked="{Binding FileStats.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
<MenuItem Header="{Binding Exported.Title, Mode=TwoWay}" IsChecked="{Binding Exported.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
<MenuItem Header="{Binding ExportedResult.Title, Mode=TwoWay}" IsChecked="{Binding ExportedResult.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
<MenuItem Header="{Binding Manifest.Title, Mode=TwoWay}" IsChecked="{Binding Manifest.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
</MenuItem>
<MenuItem Header="Layout">
<MenuItem Header="Load" Command="{Binding LoadLayoutCommand, ElementName=mainWindow}"/>
<MenuItem Header="Save" Command="{Binding SaveLayoutCommand, ElementName=mainWindow}"/>
<MenuItem Header="Dump to Console" Click="OnDumpToConsole"/>
</MenuItem>
</Menu><!--AnchorablesSource="{Binding Tools}" DocumentsSource="{Binding Files}"-->
<avalonDock:DockingManager x:Name="dockManager"
AnchorablesSource="{Binding Tools}"
DocumentsSource="{Binding Files}"
ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
Grid.Row="1" >
<avalonDock:DockingManager.LayoutItemTemplateSelector>
<local:PanesTemplateSelector>
<local:PanesTemplateSelector.FileStatsViewTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding FileSize}"/>
<TextBlock Text="{Binding LastModified}"/>
<TextBox Text="test"/>
</StackPanel>
</DataTemplate>
</local:PanesTemplateSelector.FileStatsViewTemplate>
</local:PanesTemplateSelector>
</avalonDock:DockingManager.LayoutItemTemplateSelector>
<avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<local:PanesStyleSelector>
<local:PanesStyleSelector.ToolStyle>
<Style TargetType="{x:Type avalonDock:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
</Style>
</local:PanesStyleSelector.ToolStyle>
</local:PanesStyleSelector>
</avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<avalonDock:DockingManager.LayoutUpdateStrategy>
<local:LayoutInitializer/>
</avalonDock:DockingManager.LayoutUpdateStrategy>
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal" >
<avalonDock:LayoutAnchorablePane Name="ToolsPane" DockHeight="150" >
</avalonDock:LayoutAnchorablePane>
<avalonDock:LayoutDocumentPane />
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
</Grid>
this seems to work, but take care that the sample is saving the state
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal">
<avalonDock:LayoutAnchorablePane Name="ToolsPane" DockWidth="100">
<avalonDock:LayoutAnchorable>
<TextBlock>tototo</TextBlock>
</avalonDock:LayoutAnchorable>
</avalonDock:LayoutAnchorablePane>
<avalonDock:LayoutDocumentPane/>
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>

Binding an image in a datatemplate

I'm trying to add a menu to my application, I'd like that my menu header is the currently connected user's picture.
My issue is that every binding works except the one for the image, from what I've understood on the net the DataTemplate I use to replace the menu header by a picture doesn't have access to it's parent Datacontext. I tried to use some stuff like relative source and other tricks but with no luck (certainely related to the fact that I'm new in mvvm and I obviously still have a lot to learn :) )
Here's the code I'm using :
<Grid DataContext="{Binding User}">
<DockPanel>
<Label Content="{Binding Strings.Hello, Source={StaticResource StringLocalizer} }" VerticalAlignment="Center" Padding="0,0,5,0" FontFamily="{DynamicResource Font_Normal}" FontSize="15" Foreground="White"/>
<TextBlock Text="{Binding DisplayName, TargetNullValue='Guest', FallbackValue='Guest'}" VerticalAlignment="Center" HorizontalAlignment="Left" FontFamily="{DynamicResource Font_Normal}" FontSize="15" Foreground="White"/>
<Menu Name="LogonMenu" Margin="10,0,0,0" DataContext="{Binding User}">
<MenuItem >
<MenuItem.HeaderTemplate>
<DataTemplate>
<!--<Image Source="{Binding Datacontext.Image,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Application}}, Converter={StaticResource ImageConverter}, FallbackValue={StaticResource DefaultUserIcon}}"/>-->
<Image DataContext="{Binding User}" Source="{Binding Path=Image, Converter={StaticResource ImageConverter}, FallbackValue={StaticResource DefaultUserIcon},Mode=TwoWay}"/>
</DataTemplate>
</MenuItem.HeaderTemplate>
<MenuItem Header="{Binding Strings.SignIn, Source={StaticResource StringLocalizer}}" Width="150" Margin="10,0,0,0" IsEnabled="{Binding Connected, Converter={StaticResource BoolInverterConverter}}" Visibility="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsEnabled, Converter={StaticResource BoolToVisibilityConverter}}" Command="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.SignInCommand}"/>
<MenuItem Header="{Binding Strings.SignOut, Source={StaticResource StringLocalizer}}" Margin="10,0,0,0" IsEnabled="{Binding Connected}" Visibility="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsEnabled, Converter={StaticResource BoolToVisibilityConverter}}" Command="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.SignOutCommand}"/>
<MenuItem Header="{Binding Strings.UserInformation, Source={StaticResource StringLocalizer}}" Margin="10,0,0,0" IsEnabled="{Binding Connected}" Visibility="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsEnabled, Converter={StaticResource BoolToVisibilityConverter}}"/>
</MenuItem>
</Menu>
</DockPanel>
</Grid>
In my case the image always shows the fallback picture, if someone could help me finding a way to have my user's picture it would be great.

WPF Merge ContextMenues in XAML

is it possible to merge two ContextMenues in XAML?
I created two ContextMenues as resources. I use them in a couple of DataTemplates and it works fine. However, for some DataTemplates, I would like to merge the two ContextMenues. Unfortunately, this does not seem to work.
Here's a bit of the code from one of these ContextMenues, the other ones are defined the same:
<ContextMenu x:Key="CtxIEditableViewModel" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit" Command="{Binding Path=DataContext.EditCommand}" CommandParameter="{Binding }">
<MenuItem.Icon>
<Image Source="{StaticResource IcoEdit}" Width="16" Height="16"></Image>
</MenuItem.Icon>
</MenuItem>
...
Using one of those ContextMenues works fine:
<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource CtxIEditableViewModel}">
But how to merge two? This does not work
<StackPanel Orientation="Horizontal">
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<StaticResource ResourceKey="CtxIEditableViewModel" />
<StaticResource ResourceKey="CtxRootViewModel" />
</CompositeCollection>
</ContextMenu.ItemsSource>
And this does not work either:
<StackPanel Orientation="Horizontal">
<ContextMenu>
<StaticResource ResourceKey="CtxIEditableViewModel" />
<StaticResource ResourceKey="CtxRootViewModel" />
</ContextMenu>
When I run the programm an exception is thrown saying that the context menu may not contain a logical or visual parent. Since it works fine if I only use one ContextMenu, I do not understand the exception message.
How can I merge those two ContextMenues in XAML (or is it not possible at all)?
here one way to do it using CompositeCollection
<Window.Resources>
<x:Array Type="{x:Type sys:Object}" x:Key="CtxIEditableViewModel">
<MenuItem Header="Edit1"/>
<MenuItem Header="Edit2"/>
</x:Array>
<x:Array Type="{x:Type sys:Object}" x:Key="CtxRootViewModel">
<MenuItem Header="Root1" />
<MenuItem Header="Root2"/>
</x:Array>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="LightBlue">
<Border.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{StaticResource CtxIEditableViewModel}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Border.ContextMenu>
</Border>
<Border Grid.Row="1" Background="LightGreen">
<Border.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{StaticResource CtxRootViewModel}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Border.ContextMenu>
</Border>
<Border Grid.Row="2" Background="Khaki">
<Border.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{StaticResource CtxIEditableViewModel}" />
<CollectionContainer Collection="{StaticResource CtxRootViewModel}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Border.ContextMenu>
</Border>
</Grid>

WPF Datagrid dgDataGrid_Loaded event triggers more than once

I have a wpf dadatagrid and every time the contents being loaded the dgDataGrid_Loaded event triggers twice.
I am not sure whether this is WPF bug or I have missed something!?
here is my Xaml code:
<my:DataGrid Name="dgDataGrid" DockPanel.Dock="Top"
AutoGenerateColumns="False" ClipboardCopyMode="ExcludeHeader"
CanUserDeleteRows="True"
SelectionMode="Extended" SelectionUnit="FullRow"
FontFamily="Tahoma"
ItemsSource="{Binding}"
VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingStackPanel.IsVirtualizing="True"
EnableRowVirtualization="false"
EnableColumnVirtualization="False"
IsSynchronizedWithCurrentItem="True"
BorderBrush="Blue"
RowBackground="White"
HorizontalGridLinesBrush="Blue"
GridLinesVisibility="Horizontal" VerticalGridLinesBrush="Blue" IsTextSearchEnabled="False"
IsTabStop="True" HeadersVisibility="All"
Loaded="dgDataGrid_Loaded" ContextMenuOpening="dgDataGrid_ContextMenuOpening"
LoadingRow="dgDataGrid_LoadingRow">
<my:DataGrid.Resources>
</my:DataGrid.Resources>
<my:DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type my:DataGridRow}}, Path=Header}"></TextBlock>
</DataTemplate>
</my:DataGrid.RowHeaderTemplate>
<my:DataGrid.ColumnHeaderStyle>
<Style TargetType="my:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Blue"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</my:DataGrid.ColumnHeaderStyle>
<my:DataGrid.ContextMenu>
<ContextMenu Name="cmDataGrid" StaysOpen="True">
<MenuItem Name="mnuView" Header="نمایش">
<MenuItem Name="mnuHideColumn" Header="Hide Column" Click="mnuHideColumn_Click"/>
<MenuItem Name="mnuShowColumn" Header="Show Column"/>
<Separator/>
<MenuItem Name="mnuGroupByColumn"
Header="Group by this column" Click="mnuGroupColumn_Click" />
<MenuItem Name="mnuClearGroups"
Header="Clear grouping" Click="mnuGroupColumn_Click" />
<Separator/>
<MenuItem Header="Header Alignment">
<MenuItem Name="mnuHeaderCenter" Header="Center"/>
<MenuItem Name="mnuHeaderLeft" Header="Left"/>
<MenuItem Name="mnuHeaderRight" Header="Right"/>
</MenuItem>
<MenuItem Header="Content Alignment">
<MenuItem Name="mnuContentCenter" Header="Center"/>
<MenuItem Name="mnuContentLeft" Header="Left"/>
<MenuItem Name="mnuContentRight" Header="Right"/>
</MenuItem>
</MenuItem>
</ContextMenu>
</my:DataGrid.ContextMenu>
</my:DataGrid>
Any suggestions?

Resources