I am working on a project in WPF. I have listview control and in that listview I have textblock and button as a template controls.
I want that when user click the button the popup open and shows the infos of selected item. But when clicked the button popup shows up multiple times (count of items).
These are the XAML codes.
<Window x:Class="TestingPopupShow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:TestingPopupShow.ViewModel"
xmlns:local="clr-namespace:TestingPopupShow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="400">
<Window.Resources>
<ResourceDictionary>
<vm:ItemInfosPopupVM x:Key="vm"/>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="SubGrid" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListView x:Name="listView"
Grid.Row="1"
Margin="0 5 0 0">
<ListView.ItemTemplate>
<DataTemplate>
<Border x:Name="debugPanel" CornerRadius="3" BorderBrush="Black" BorderThickness="0.5" Grid.Column="0" Grid.RowSpan="2">
<Grid DataContext="{StaticResource vm}" x:Name="listViewGrid" Margin="1"
HorizontalAlignment="Center"
Background="#F2F2F2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="25"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="W01"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
<TextBlock Text="1 pcs"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
<TextBlock Text="1200 X 1600"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
</StackPanel >
<DockPanel x:Name="imageDockPanel" Grid.Column="1">
</DockPanel >
<Button Grid.Column="2"
BorderThickness="0"
Command="{Binding showPopupCommand}"
x:Name="buttonOpen"
Content=">"
HorizontalAlignment="Stretch"/>
<Popup x:Name="itemInfosPopup"
StaysOpen="False"
Placement="Mouse"
IsOpen="{Binding PopupVis, UpdateSourceTrigger=PropertyChanged}"
AllowsTransparency="True">
<Border BorderBrush="Black" BorderThickness="2">
<StackPanel Background="White" Width="200" Height="300">
</StackPanel>
</Border>
</Popup>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
This the ViewModel Class
public class ItemInfosPopupVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool popupVis;
public bool PopupVis
{
get { return popupVis; }
set
{
popupVis = value;
OnPropertyChanged("PopupVis");
}
}
public ShowPopupCommand showPopupCommand { get; set; }
public ItemInfosPopupVM()
{
PopupVis = false;
showPopupCommand = new ShowPopupCommand(this);
}
public void ShowPopup()
{
if (PopupVis)
{
PopupVis = false;
}
else
{
PopupVis = true;
}
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
These are command class:
public class ShowPopupCommand : ICommand
{
public ItemInfosPopupVM ViewModel { get; set; }
public event EventHandler CanExecuteChanged;
public ShowPopupCommand(ItemInfosPopupVM vm)
{
ViewModel = vm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
ViewModel.ShowPopup();
}
}
These are temporary codes for testing in the main window view
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Temporary codes. Testing listview.
for (int i = 0; i < 5; i++)
{
listView.Items.Add("Item " + i.ToString());
}
}
}
I think I'm creating the popup control in the wrong place in XAML. But i can not figure out.
You incorrectly implement the data context (ViewModel) and commands.
Here's an example based on base classes from here: BaseInpc and RelayCommand.
public class ItemInfosPopupVM : BaseInpc
{
private bool popupVis;
private string title = string.Empty;
public bool PopupVis { get => popupVis; set => Set(ref popupVis, value); }
public string Title { get => title; set => Set(ref title, value ?? string.Empty); }
}
public class ItemsVM
{
public ObservableCollection<ItemInfosPopupVM> ItemInfos { get; } = new();
public ItemsVM()
{
// Temporary codes. Testing listview.
for (int i = 0; i < 5; i++)
{
ItemInfos.Add(new ItemInfosPopupVM { Title = "Item " + i.ToString() });
}
InvertPopupVis = new RelayCommand<ItemInfosPopupVM>
(
item => item.PopupVis = !item.PopupVis
);
}
public RelayCommand<ItemInfosPopupVM> InvertPopupVis { get; }
}
<Window x:Class="TestingPopupShow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:TestingPopupShow.ViewModel"
xmlns:local="clr-namespace:TestingPopupShow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="400"
DataContext="{DynamicResource vm}">
<Window.Resources>
<vm:ItemsVM x:Key="vm"/>
</Window.Resources>
<Grid x:Name="SubGrid" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding ItemInfos}"
Grid.Row="1"
Margin="0 5 0 0">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type vm:ItemInfosPopupVM}">
<Border CornerRadius="3" BorderBrush="Black" BorderThickness="0.5" Grid.Column="0" Grid.RowSpan="2">
<Grid Margin="1"
HorizontalAlignment="Center"
Background="#F2F2F2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="25"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Title, StringFormat='{}{0} - W01'}"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
<TextBlock Text="1 pcs"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
<TextBlock Text="1200 X 1600"
FontSize="12"
Margin="5"
FontFamily="Tohama"/>
</StackPanel >
<DockPanel x:Name="imageDockPanel" Grid.Column="1">
</DockPanel >
<Button Grid.Column="2"
BorderThickness="0"
Command="{Binding InvertPopupVis, Source={StaticResource vm}}"
CommandParameter="{Binding}"
Content=">"
HorizontalAlignment="Stretch"/>
<Popup StaysOpen="False"
Placement="Mouse"
IsOpen="{Binding PopupVis, UpdateSourceTrigger=PropertyChanged}"
AllowsTransparency="True">
<Border BorderBrush="Black" BorderThickness="2">
<StackPanel Background="White" Width="200" Height="300">
</StackPanel>
</Border>
</Popup>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>