I have a problem with Menu Item Command Binding. I have used MVVM pattern
When I use right click, the menu appears. But when I click on the menu item doesn't work. Do you know why? Thanks
Here is the XAML:
<UserControl x:Class="PlotView.ViewModel.PlotViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d"
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
d:DesignHeight="400" d:DesignWidth="600"
x:Name="theViewName">
<UserControl.Resources>
</UserControl.Resources>
<GroupBox Name="GB" Header="Graphs" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="0">
<ListView Name="PlotLista" SelectedIndex="{Binding SelectedValue}" ItemsSource="{Binding PlotModelList}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate>
<oxy:Plot MinHeight="260" Height="Auto" IsRendering="True" FontStyle="Normal" FontFamily="Arial" FontSize="8" VerticalContentAlignment="Top" HorizontalContentAlignment="Left" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ActualWidth}" Model="{Binding }">
<oxy:Plot.ContextMenu>
<ContextMenu>
<MenuItem Header="Export to PNG" Command="{Binding DataContext.SavePNG, ElementName=theViewName}"/>
</ContextMenu>
</oxy:Plot.ContextMenu>
</oxy:Plot>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</GroupBox>
</UserControl>
Here are a small portion of ViewModel:
#region Fields
private readonly DelegateCommand _menuClick=new DelegateCommand(this.MenuItemClick);
#endregion
#region Command
public ICommand SavePNG
{
get { return this._menuClick; }
}
#endregion
private void MenuItemClick()
{
// some code here
}
Error:
System.Windows.Data Error: 40 : BindingExpression path error:
'SavePNG' property not found on 'object' ''PlotModel'
(HashCode=15385318)'. BindingExpression:Path=SavePNG;
DataItem='PlotModel' (HashCode=15385318); target element is 'MenuItem'
(Name=''); target property is 'Command' (type 'ICommand')
Your binding is trying to find SavePNG on your Item, not your ViewModel.
Instead, give your view an x:Name, or a Name, and use the following binding instead:
{Binding DataContext.SavePNG, ElementName=theViewName}
Assuming that SaveCommand is on the same ViewModel which contains your collection.
ContextMenus are a little different in wpf as they are not part of the visual tree of the control. As such they cannot 'see' any elements by relative source or by elementnames.
A little cheat is to use the PlacementTarget property and get the datacontext with that. Change your ListView to below to make it work. Notice the tag property on the ListView and the DataContext property on the ContextMenu.
<ListView Name="PlotLista" SelectedIndex="{Binding SelectedValue}" ItemsSource="{Binding PlotModelList}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Tag="{Binding DataContext,ElementName=theViewName}">
<ListView.ItemTemplate>
<DataTemplate>
<oxy:Plot MinHeight="260" Height="Auto" IsRendering="True" FontStyle="Normal" FontFamily="Arial" FontSize="8" VerticalContentAlignment="Top" HorizontalContentAlignment="Left" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ActualWidth}" Model="{Binding }">
<oxy:Plot.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Export to PNG" Command="{Binding SavePNG}"/>
</ContextMenu>
</oxy:Plot.ContextMenu>
</oxy:Plot>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This wasn't written in visual studio so please check the syntax:
<ListView Tag="{Binding Path=DataContext,ElementName=theViewName}">
<ListView.ItemTemplate>
<DataTemplate>
<oxy:Plot Tag="{Binding Path=Tag,RelativeSource={RelativeSource AncestorType=ListView}">
<oxy:Plot.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Command="{Binding SavePNG}"/>
</ContextMenu>
</oxy:Plot.ContextMenu>
</oxy:Plot>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Related
I'm quite new to WPF and C#. I'm trying to catch a double click event in an user control and handle it through an ICommand.
Here is how i'm trying to do that:
User Control:
<UserControl x:Class="MyNamespace.View.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:MyNamespace.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
DataContext="{Binding MyViewModelClass, Source={StaticResource Locator}}"
>
<UserControl.Resources>
<DataTemplate x:Key="MyTemplate">
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DataContext.HandleDoubleClickCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<WrapPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="12" >
<TextBlock Text="Data: "><Run FontWeight="Light" Text="{Binding data}"/></TextBlock>
</WrapPanel>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{DynamicResource ColorPanel2}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="0 0 0 1">
<WrapPanel Margin="12" VerticalAlignment="Center">
<TextBlock FontWeight="Bold" Margin="8" VerticalAlignment="Center" FontSize="18"
Text="some text: ">
</TextBlock>
</WrapPanel>
</Border>
<ListView Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding SelectedItem.listElement, UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{StaticResource MyTemplate}"
SelectedItem="{Binding SelectedItem}"
/>
</Grid>
</UserControl>
And i placed the command to handle the event in the ViewModel class:
ICommand _HandleDoubleClickCommand;
public ICommand HandleDoubleClickCommand
{
get
{
if (_HandleDoubleClickCommand == null)
{
_HandleDoubleClickCommand = new RelayCommand<object>(ExecuteHandleDoubleClickCommand, CanExecuteHandleDoubleClickCommand);
}
return _HandleDoubleClickCommand;
}
}
private bool CanExecuteHandleDoubleClickCommand(object arg)
{
return true;
}
private void ExecuteHandleDoubleClickCommand(object obj)
{
System.Windows.MessageBox.Show("HandleDoubleClickCommand");
}
So, basically i have a list of elements and i want to handle the double click event on is.
The behavior i see is that sometimes the HandleDoubleClickCommand gets executed, sometimes it's not. I don't see any exception thrown and i checked with the debugger that the code is executed only when the message box is shown.
I also tried to use InputBindings instead of Interaction.Triggers:
<ContentControl.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding DataContext.HandleDoubleClickCommand, RelativeSource={RelativeSource AncestorType=UserControl}, diag:PresentationTraceSources.TraceLevel=High}" />
But i see the same behavior. Enabling the TraceLevel=High didn't give me useful info..
Also, i tried to handle the right click event instead of the double click, but still, the command gets executed only sometimes.
I think i'm missing something here, could someone help me to understand what the issue is? or at least give me some advice on how i can debug the problem..
Thank you
UPDATE
I found out that the command gets always executed if i double click on the element text. The thing is that i would like it to be executed even if i double click on an empty space of the selected row of the ListView...
Move the Margin from the WrapPanel to the TextBlock and define an ItemContainerStyle that makes the contents of the ListViewItem stretch horizontally.
You should also set the Background property of the WrapPanel to capture the clicks:
<ListView Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding SelectedItem.listElement}"
SelectedItem="{Binding SelectedItem}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DataContext.HandleDoubleClickCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<WrapPanel Background="Transparent">
<TextBlock Text="Data: " Margin="12"><Run FontWeight="Light" Text="{Binding data}"/></TextBlock>
</WrapPanel>
</ContentControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have a task to use a contextmenu in treeview and pass selected treeview's item to ViewModel by clicking on contextmenu element.
Here is my xaml:
<Window.Resources>
<HierarchicalDataTemplate x:Key="Ufps"
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Margin="5 0 0 0" Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
........
........
<TreeView x:Name="TrvUfpsDictionary" Height="222" Canvas.Left="25"
Canvas.Top="280" Width="545"
Background="AliceBlue"
ItemsSource="{Binding Path=Ufps, Mode=OneWay}"
ItemTemplate="{StaticResource Ufps}">
<TreeView.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Element"
cal:Message.Attach="[Event Click] = [Action AddElement(TrvUfpsDictionary.SelectedItem)]"
/>
................
</ContextMenu>
</TreeView.ContextMenu>
</TreeView>
........
<Button Content="Test" Canvas.Left="475" Canvas.Top="568" Width="75"
cal:Message.Attach="[Event Click] = [Action AddElement(TrvUfpsDictionary.SelectedItem)]"/>
And here is simple ViewModel's code:
public class UserSettingsViewModel : PropertyChangedBase
{
..........
public void AddElement(object selectedItem)
{
MessageBox.Show("Element added! "+selectedItem.?GetHashCode());
}
..........
}
Now I've stuck with it. When I've selected treeview's item and then I've pressed the "Test" button - it works fine, it pass the selected item to "AddElement" in my VM. BUT when I do the same with contextmenu - it always pass null. Did I miss something?
EDIT
I've made a simple app with the problem described. https://github.com/whizzzkey/WpfApp1
You might have to move the Context Menu further into the TreeView, into the Item Template and add Context Menu to the Label/TextBlock you have in nodes.
For example, consider the following Employee tree (emulating since I do not know your data structure),
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Positions}" >
<Label Content="{Binding DepartmentName}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Employees}" >
<Label Content="{Binding PositionName}"
Tag="{Binding DataContext, ElementName=TestControl}" >
<Label.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Element"
cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]"/>
</ContextMenu>
</Label.ContextMenu>
</Label>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<Label Content="{Binding EmployeeName}"
Tag="{Binding DataContext, ElementName=TestControl}">
<Label.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Element"
cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]" />
</ContextMenu>
</Label.ContextMenu>
</Label>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
There are couple of important points to note here. Since your method exists in ViewModel and you have to ensure that the DataContext is pointing to your ViewModel instead of the Item Type that is bound to node.
For this, you need can make use of cal:Action.TargetWithoutContext. The following line the Label definition ensure we have access to the View's DataContext.
Tag="{Binding DataContext, ElementName=TestControl}"
While the following line ensures the we get our bindings right (to ViewModel). TestControl is the x:Name for your UserControl
cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"
Finally the Click Action would be modified as following.
cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]"
This would ensure your ViewModel's Action is called with the right parameter passed.
Update
Based on your comment and code,following are the changes required.
Window Definition : Add x:Name
<Window
x:Class="WpfApp1.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org"
Title="XmlData Tree Test"
x:Name="TestControl"
Width="250"
Height="350">
Root Hierarchical Template
Associating Item source with Tag is placed on the TextBlock, also the Relative Source has Self.
<HierarchicalDataTemplate DataType="root" ItemsSource="{Binding XPath=./*}" >
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0" Text="ROOT"
Tag="{Binding DataContext, ElementName=TestControl}">
<TextBlock.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Element"
cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
Hierarchical Template for Node
<HierarchicalDataTemplate
DataType="Node"
ItemsSource="{Binding XPath=./*}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0" Text="Node:" />
<TextBlock Margin="5,0,0,0"
Tag="{Binding DataContext, ElementName=TestControl}"
Text="{Binding XPath=#name}" >
<TextBlock.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Element"
cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
Output Example,
For Root
For Node,
I'am really having some problems with the ContextMenu from Caliburn.Micro. No matter what I do, I get the error "Cant' find the method ...".
I've tried this solutions, and that one too, but I can't get this to work.
What I'am doing wrong? Actually, there's a way to debug the view and find out in which Context the control is searching for the respective ViewModel?
And another thing... this View is inside a DataTemplate from another view, does that change anything? All the others bindings are working from the correct ViewModel...
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Grid.Row="1" Grid.Column="0"
Padding="10,5,15,5"
MaxHeight="390" x:Name="xImages">
<ItemsControl
ItemsSource="{Binding Path=Document.Images}"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Height="110">
<Border Margin="5" BorderBrush="Gainsboro" BorderThickness="1">
<Image Source="{Binding Path=PathThumb}" Width="70" Height="100"> <!-- Tag="{Binding DataContext, ElementName=xImagens}" -->
<Image.ContextMenu>
<ContextMenu
cal:Action.TargetWithoutContext="{Binding DataContext, ElementName=xImagens}"> <!--PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"-->
<MenuItem Header="Ampliar"
cal:Message.Attach="[Event Click] = [Action ExpandImage($datacontext)]"></MenuItem>
<MenuItem Header="Excluir"
cal:Message.Attach="[Event Click] = [Action DeleteImage($datacontext)]"></MenuItem>
</ContextMenu>
</Image.ContextMenu>
</Image>
</Border>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
cal:Action.TargetWithoutContext="{Binding Source={x:Reference xImagens} , Path=DataContext}">
Because ContextMenu is not part of the VisualTree , you can't bind to elements in the visual tree
of it's TargetPlacement. ( Though in XAML it seems like it is part of it ).
You have two choices:
{Binding Path=PlacementTarget.DataContext}
Or:
{Binding Source={x:Reference xImagens}, Path=DataContext}
give the x:Name="xImages" to the ItemsControl and then do the binding with ElementName to the ContextMenu using the Action.TargetWithoutContext, you had it right but the ScrollViewer isn't what has the Datacontext to the List of data, the ItemControl does since it has the ItemSource.
Was there a reason for naming the ScrollViewer?
<ItemsControl x:Name="xImages">
<ContextMenu Action.TargetWithoutContext="{Binding Path=DataContext, ElementName=xImages}">
<!-- Shortened -->
</ContextMenu>
</ItemsControl>
I have a NavigateToAccountsCommand RelayCommand property in the ViewModel. When I bind the same to a button on the page anywhere outside the ListView the command binding is working. However as soon as I move this to a ListView's DataTemplate its not working.
I have tried changing the binding from NavigateToAccountsCommand to DataContext.NavigateToAccountsCommand still not working.
Appreciate your help...
<Page
x:Class="FinancePRO.App.Views.AccountsView"
DataContext="{Binding AccountsViewModel, Source={StaticResource MainViewModelLocator}}"
mc:Ignorable="d">
<Grid>
<!--**This one is working**-->
<Button Command="{Binding NavigateToAccountsCommand}" >
<!--**This one is not working**-->
<ListView ItemsSource="{Binding AllAccounts}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding AccountName}"/>
<Button Command="{Binding NavigateToAccountsCommand}">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When you are inside the DataTemplate of the ListView, your data context is the current item of the ListView's ItemsSource. As there is nothing called "NavigateToAccountsCommand" property within your AllAcounts' each individual element, binding isn't working.
To fix that, you will need to reference something from the outside of DataTemplate; following should work. It changes the binding to reference the root Grid's DataContext which should have the property NavigateToAccountsCommand accessible. To reference the grid, you have to add Name attribute, and then use ElementName binding.
<Grid Name="Root">
<!--**This one is working**-->
<Button Command="{Binding NavigateToAccountsCommand}" >
<!--**This one is not working**-->
<ListView ItemsSource="{Binding AllAccounts}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding AccountName}"/>
<Button Command"{Binding ElementName=Root, Path=DataContext.NavigateToAccountsCommand}">
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
You can use
<Button x:Name="cmdTabItemCloseButton"
Style="{StaticResource TabItemCloseButtonStyle}"
Grid.Column="1" Margin="15,0,0,0"
Command="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type ListView}},
Path=DataContext.NavigateToAccountsCommand}"
CommandParameter="{Binding}"/>
I had a similar problem (Win RT) which I solved by just using:
<GridView
x:Name="itemGridView"
ItemClick="ItemView_ItemClick"
IsItemClickEnabled="True"/>
and then in the Page class:
private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
//e is the object being clicked
}
I'm trying to bind the SelectedItem to a View. But the view is not able to access the viewmodel when it is inside the Resources block.
When the datacontext is re-assigned to the children, the binding works for textblocks but not for UserControl (NoteView)
Am I missing any Binding?
PFB revised(entire) code and inline comments.
<UserControl x:Class="Konduva.View.NoteSearchView"
<!-- other namespaces here -->
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding NoteSearch, Source={StaticResource Locator}}">
<Grid>
<ListView ItemsSource="{Binding Notes}"
SelectedItem="{Binding SelectedNote}">
<ListView.Resources>
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<!-- This is working --> <TextBlock Text="{Binding SelectedNote.Title}" />
<!-- This is not working --> <v:NoteView DataContext="{Binding SelectedNote}" />
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
</ListView.Resources>
</ListView>
</Grid>
</UserControl>
NoteView:
<Grid>
<TextBlock Text="{Binding Title}" /> // This Text is not displayed
</Grid>
Update 3
Since you're using MvvmLight: in NoteView, try changing
DataContext="{Binding Note, Source={StaticResource Locator}}"
to
<UserControl.Style>
<Style TargetType="UserControl">
<Setter Property="DataContext" Value="{Binding Note, Source={StaticResource Locator}}"/>
</Style>
</UserControl.Style>
Update 2
Encountered a similar problem a few minutes ago which I didn't fully understand so I'll throw in the same solution here to see if it helps. What happends if you change it to this?
<v:NoteView DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Popup}},
Path=DataContext.SelectedNote}"/>
Update
I'm unable to reproduce this. Try adding this in your NoteView constructor. Do you reach DataContextChangedHandler when you change the selection in the ListView?
public NoteView()
{
InitializeComponent();
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(UserControl.DataContextProperty,
typeof(UserControl));
if (dpd != null)
{
dpd.AddValueChanged(this, new EventHandler(DataContextChangedHandler));
}
}
void DataContextChangedHandler(object sender, EventArgs e)
{
MessageBox.Show("DataContext Changed: " + DataContext);
}
First answer
Your DockPanel will get the NoteViewModel as a DataContext and not the ListView and since this DataContext is inherited by all Childs every child will end up with a NoteViewModel as DataContext. To use the ListView as a DataContext for the Popup you can do this. I'm not sure what the DataContext Binding for the StackPanel does though, so I might be missing something here..
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<TextBlock Text="{Binding SelectedNote.Title}" />
<StackPanel>
<v:NoteView DataContext="{Binding SelectedNote}"/>
</StackPanel>
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
Instead of inserting a NoteView directly and binding the DataContext, use a ContentPresenter:
<ContentPresenter Content="{Binding SelectedNote}>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<v:NoteView />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>