我正在 WPF 中开发一个项目。我有列表视图控件,在该列表视图中我有文本块和按钮作为模板控件。
我希望当用户单击按钮时弹出窗口打开并显示所选项目的信息。但是,当单击按钮时,弹出窗口会多次显示(项目计数)。
这些是 XAML 代码。
<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>
这是 ViewModel 类
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));
}
}
这些是命令类:
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();
}
}
这些是在主窗口视图中测试的临时代码
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());
}
}
}
我认为我在 XAML 中的错误位置创建了弹出控件。但我无法弄清楚。
您错误地实现了数据上下文 (ViewModel) 和命令。
以下是基于此处的基类的示例:BaseInpc 和 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>