Reputation: 522
I have a ListView
with a DataTemplate
, inside this templates there are several textblocks and a button. The button has a contextmenu with fixed items. The binding of the listviewitems works fine, but binding a property to the contextmenu does not seem to work.
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Grid.Column="0" Grid.RowSpan="2" Background="{Binding StateColor}">
</Grid>
<TextBlock Grid.Column="1" Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Anrufen" Name="mn_call" Click="mn_call_Click" DataContext={Binding Number} />
</ContextMenu>
</Button.ContextMenu> ...</Button>
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstEntry.KDKGRS}" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="{Binding FirstEntry.ConvertedKGFARBE}" />
<TextBlock Text="{Binding FirstEntry.ADNAMI}" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have removed some unnecessary bits of the code (style and columndefinitions) for readability.
The important part is the MenuItem
inside the Button
. My underlying class has a public string property Number
. This should be passed to the menu item. But the DataContext
of the MenuItem
is always null inside the click event.
I've read something about the contextmenu not beeing part of the visual tree, but I can't wrap my head around it. Could somebody explain the issue with the binding?
Edit Code for the underlying class: Again removed some unnecessary code for the question
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
And the binding of the ListBox:
List<PhoneClient> clients = new List<PhoneClient>();
clients = load(); //returns active Clients
lv_clients.ItemsSource = clients;
Upvotes: 0
Views: 1247
Reputation: 11221
Bridging the gap
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Anrufen" Click="mn_call_Click" Name="mn_call"
DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
Handler
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
// Do Stuff
}
EDIT
MainWindow.xaml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="10">
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="LightGray" Width="100">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Background="LightGreen">
</Grid>
<TextBlock Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Show" Click="mn_call_Click" Name="mn_call" DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
</Button.ContextMenu> ...
</Button>
<StackPanel Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Foo" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="Blue" />
<TextBlock Text="Bar" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
namespace WpfApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<PhoneClient> clients = new List<PhoneClient>();
clients.Add(new PhoneClient() { Name = "Kumar", Number = "0101010", Extension = "555", State = "New York" });
clients.Add(new PhoneClient() { Name = "Shanaya", Number = "1010101", Extension = "555", State = "New Jersey" });
clients.Add(new PhoneClient() { Name = "Billy Bob", Number = "6543210", Extension = "555", State = "Single" });
lv_clients.ItemsSource = clients;
}
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String State { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
MessageBox.Show("Number " + number);
}
private void Button_ListItem_Click(object sender, RoutedEventArgs e)
{
Button currentButton = (Button)sender;
PhoneClient data = (PhoneClient)currentButton.DataContext;
MessageBox.Show(data.Name + " tapped");
}
}
}
Upvotes: 1