Caliburn Micro with TreeView ContextMenu target does not exist - wpf

It seems (from other posts with similar problems) that I am trying to bind the target to an element which doesn't exist in the same visual tree. I have a ContextMenu on the 3rd level in the TreeView, and am trying to set an action to execute a method on the ViewModel via the Tag of the parent element (TextBlock), but can't get it to work.
The XAML is:
<HierarchicalDataTemplate x:Key="FeatureTemplate">
<Grid HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Name}" Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
<telerik:RadContextMenu.ContextMenu >
<telerik:RadContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"
cal:Message.Attach="[Event Opened] = [Action ContextMenuOpened($source)]">
<telerik:RadMenuItem Header="Export" cal:Message.Attach="[Event Click]=[Action ContextMenuClick($source)]"/>
</telerik:RadContextMenu>
</telerik:RadContextMenu.ContextMenu>
</TextBlock>
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="FormTemplate"
ItemTemplate="{StaticResource FeatureTemplate}"
ItemsSource="{Binding List}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}" Width="32" Height="32" HorizontalAlignment="Right" Margin="0,3"/>
<TextBlock Grid.Column="1" Text="{Binding Name}" VerticalAlignment="Center" Margin="5"/>
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="JobTemplate"
ItemTemplate="{StaticResource FormTemplate}"
ItemsSource="{Binding List}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<telerik:RadTreeView Name="TreeView1"
Grid.Row="2"
cal:Message.Attach="[Event SelectionChanged] = [Action SetSelectedItem($this.SelectedItem)]"
Background="White"
ItemsSource="{Binding AvailableData}"
ItemTemplate="{StaticResource JobTemplate}"
telerik:AnimationManager.IsAnimationEnabled="False" >
</telerik:RadTreeView>
ViewModel code:
public void ContextMenuOpened(FrameworkElement source){}
I get the error that ContextMenuOpened target is not found.
Any help or suggestions would be much appreciated.

Related

Synchronize the size of controls that lay in different ItemsCollections

I want to synchronize the width of two controls.
<!--DataContext-->
<DockPanel LastChildFill="True" x:Name="HeaderDockPanel">
<DockPanel LastChildFill="True" MinHeight="60" DockPanel.Dock="Top" DataContext="{Binding Month}" d:DataContext="{d:DesignInstance Type=local:Month}" >
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlock}" DockPanel.Dock="Left" />
<!--this shoud to set the Width-->
<!--Nested_1 DataContext Model_1-->
<local:DaysLine HorizontalAlignment="Left" Width="{Binding ElementName=HeaderDockPanel, Path=DataContext.DaysHeaderWidth, Mode=TwoWay}" />
</DockPanel>
<!--Nested_1 DataContext Model_2-->
<ListView Grid.Row="1" ItemsSource="{Binding CarBusiness}">
<ItemsControl.ItemTemplate>
<DataTemplate >
<DockPanel d:DataContext="{d:DesignInstance Type=local:CarBusiness}" LastChildFill="True">
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlock}" DockPanel.Dock="Left" Margin="-6 0 0 0"/>
<!--this shoud to get the Width-->
<!--Nested_2 DataContext Model_3-->
<ItemsControl ItemsSource="{Binding Business}" Style="{StaticResource HorizontalItemsControl}" Width="{Binding DaysHeaderWidth}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:BusinessTextBlock d:DataContext="{d:DesignInstance Type=local:Business}" Business="{Binding}" ColumnWidth="20" HorizontalAlignment="Left" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
</DockPanel>
The problem is that i can't find the source by RelativeSource Binding use FindByName.
The target control whatch on nested DataContext that is an item of the first and i cant set it in without adding to all this models the MyWidth property.
Is there a some enother way to bind them more correct?
I am thinking about a static property but it is not as correct as i want because i have planned to have a several instances of this control.

How to use Binding in trigger, to change another control in WPF?

I have this DataTemplate in style. I have two properties for Image's Source (Image and ImageHover). Now its Image. So I want to change it to ImageHover when the List item from the List Box is hovered by the mouse. How can I make this kind of Binding - Binding in trigger, to change another control's property ?
<DataTemplate x:Key="MetroListBoxItemTemplate">
<Grid Name="grid_menu">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="110"/>
</Grid.ColumnDefinitions>
<Image Name="menu_image" Source="{Binding Image}" Stretch="Uniform" Width="40" Height="40" >
</Image>
<StackPanel Grid.Column="1" Margin="5">
<TextBlock Text="{Binding Path=Title, FallbackValue=Title}" FontFamily="Segoe UI Light" FontSize="20"
Foreground="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}, Path=Foreground}" />
</StackPanel>
</Grid>
</DataTemplate>
I use the template here
<ListBox
x:Name="main_menu" HorizontalAlignment="Left" Margin="8,8,0,8" Width="160"
ItemTemplate="{DynamicResource MetroListBoxItemTemplate}"
ItemContainerStyle="{DynamicResource MetroListBoxItemStyle}"
ItemsSource="{Binding Menu}">
</ListBox>

Binding to the IsSelected property of the parent ListViewItem

I'm attempting to bind the Visibility property of a TextBlock that's held within the ItemTemplate for a ListView to the IsSelected property of the TextBlock's parent ListViewItem.
With this markup, the TextBlock is always visible.
<ListView x:Name="ItemListView" ItemsSource="{Binding Path=Accounts}" Margin="60,0,0,10" Grid.Row="1" Grid.Column="0">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100">
</ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Width="100" Height="100" Grid.Column="0"></Image>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Path=Account.Name}"
FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" />
</StackPanel>
<TextBlock Grid.Column="3" VerticalAlignment="Bottom"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IsSelected, Converter={StaticResource boolConverter}, Mode=OneWay}">
Show More Details...
</TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Notes:
1. In case it makes any difference, this is WinRT; a Metro app written in C#.
2. boolConverter is a fairly standard converter appears to work correctly.
Use Mode=FindAncestor:
<TextBlock Grid.Column="3" VerticalAlignment="Bottom"
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource boolConverter}, Mode=OneWay}">
I think that in this case you will have to use ElementName=ItemListView
#Murven 's answer was close. This is what worked for me:
<TextBlock Visibility="{Binding DataContext.IsSelected, ElementName=ItemListView Converter={StaticResource boolConverter}, Mode=OneWay}">
I had to use DataContext.IsSelected to access the context of the ItemListView.
Not sure if there is a better way.

change datatemplate resource runtime

I have created one datatemplate resouce in my xaml file
<navigation:Page.Resources>
<DataTemplate x:Key="PageFooter" >
<StackPanel Width="{Binding Path=UsablePageWidth, Mode=OneWay}" Height="Auto" x:Name="spFooter" HorizontalAlignment="Center">
<TextBlock x:Name="txtParameter" FontSize="16" Text="{Binding}"
FontWeight="Bold" Foreground="White"
HorizontalContentAlignment="Center"
Width="{Binding Path=UsablePageWidth, Mode=OneWay}"
Background="Black" Height="35" />
</StackPanel>
</DataTemplate>
</navigation:Page.Resources>
Now in my code behind i want to update this Textblock with my database value
How to do this? I am new in silverlight

WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference

I have the following XAML:
<UserControl x:Class="EMS.Controls.Dictionary.TOCControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:EMS.Controls.Dictionary.Models"
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
x:Name="root" >
<TreeView
x:Name="TOCTreeView"
Background="White"
Padding="3,5"
ContextMenuOpening="TOCTreeView_ContextMenuOpening"
ItemsSource="{Binding Children}" BorderBrush="{x:Null}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children, Mode=OneTime}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--<ColumnDefinition Width="Auto"/>-->
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsVisible}"/>-->
<ContentPresenter Grid.Column="0" Height="16" Width="20"
Content="{Binding LayerRepresentation}" />
<!--<ContentPresenter Grid.Column="1" >
<ContentPresenter.Content>
Test
</ContentPresenter.Content>
</ContentPresenter>-->
<TextBlock Grid.Column="2" FontWeight="Normal" Text="{Binding Path=Alias, Mode=OneWay}" >
<ToolTipService.ToolTip>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
</ToolTipService.ToolTip>
</TextBlock>
</Grid>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children, Mode=OneTime}">
<!--<DataTemplate>-->
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsVisible}"/>
<ContentPresenter Grid.Column="1"
Content="{Binding LayerRepresentation, Mode=OneWay}" />
<TextBlock Margin="0,1,0,1" Text="{Binding Path=Alias, Mode=OneWay}" Grid.Column="2">
<ToolTipService.ToolTip>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
</ToolTipService.ToolTip>
</TextBlock>
</Grid>
<!--</DataTemplate>-->
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ContextMenu>
<ContextMenu>
<MenuItem Name="miRemove" Header="Remove"
Command="{Binding ElementName=root, Path=RemoveItemCmd,
diagnostics:PresentationTraceSources.TraceLevel=High}">
<MenuItem.Icon>
<Image Source="../images/16x16/Delete.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Properties"
Command="{Binding ElementName=root, Path=GetItemPropertiesCmd}"/>
</ContextMenu>
</TreeView.ContextMenu>
</TreeView>
</UserControl>
Code behind for this UserControl has two ICommand properties with names: RemoveItemCmd and GetItemPropertiesCmd. However, I get
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=root'. BindingExpression:Path=RemoveItemCmd; DataItem=null; target element is 'MenuItem' (Name='miRemove'); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=root'. BindingExpression:Path=GetItemPropertiesCmd; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')
when UserControl is constructed. Why is this and how do I resolve?
You can't bind using element name from a context menu. The link is broken between the context menu and its placement target. You can get around it using a couple of tricks though...
Use RoutedUICommands with a command binding on the UserControl, then no binding is needed.
Use the placement target binding on the context menu's DataContext. This allows you to at least get the data context of the element the context menu appears on to the context menu.
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=PlacementTarget.DataContext}"
(and i think this is what you want) You can access a static resource, ElementSpy lets you link to the window using a static resource so you can then use a defacto ElementName bindings.
Best solution here ElementName Binding from MenuItem in ContextMenu
Just one line of code:
NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
With .NET 4.0 you can do it like this:
<MenuItem Command="{Binding CommandName, Source={x:Reference ElementName}}"/>

Resources