You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM下资源字典中DataGrid表头图片的鼠标事件与弹窗联动问题

解决ResourceDictionary中控件触发View内弹窗的联动方案

方案1:用附加属性绑定弹窗实例

这种方式直接把View里的弹窗和表头Image关联起来,逻辑清晰:

  • 先定义一个附加属性类,用来传递弹窗引用:
    public static class FilterPopupAttached
    {
        public static readonly DependencyProperty PopupProperty =
            DependencyProperty.RegisterAttached("Popup", typeof(Popup), typeof(FilterPopupAttached));
    
        public static void SetPopup(DependencyObject obj, Popup value) => obj.SetValue(PopupProperty, value);
        public static Popup GetPopup(DependencyObject obj) => (Popup)obj.GetValue(PopupProperty);
    }
    
  • 在SearchExpView.xaml里,给表头模板中的Image设置这个附加属性,绑定到你的PopupFiltre:
    <!-- 假设你的列使用了BlockStyles里的表头模板,直接在模板的Image节点上添加 -->
    <Image local:FilterPopupAttached.Popup="{Binding ElementName=PopupFiltre}" 
           MouseEnter="Image_MouseEnter" MouseLeave="Image_MouseLeave" Click="Image_Click"/>
    
  • 回到BlockStyles.xaml.cs的点击事件里,获取弹窗并控制显示:
    private void Image_Click(object sender, RoutedEventArgs e)
    {
        var image = sender as Image;
        var targetPopup = FilterPopupAttached.GetPopup(image);
        if (targetPopup != null)
        {
            targetPopup.IsOpen = !targetPopup.IsOpen;
            // 可选:把弹窗定位到Image下方,更贴合筛选场景
            targetPopup.PlacementTarget = image;
            targetPopup.Placement = PlacementMode.Bottom;
        }
    }
    

方案2:通过路由事件传递点击信号

利用WPF的路由事件冒泡特性,让View层捕获ResourceDictionary里的点击事件:

  • 在BlockStyles.xaml.cs里定义一个自定义路由事件:
    public static readonly RoutedEvent FilterClickEvent = EventManager.RegisterRoutedEvent(
        "FilterClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BlockStyles));
    
    public event RoutedEventHandler FilterClick
    {
        add => AddHandler(FilterClickEvent, value);
        remove => RemoveHandler(FilterClickEvent, value);
    }
    
    private void Image_Click(object sender, RoutedEventArgs e)
    {
        // 触发路由事件,让上层控件捕获
        RaiseEvent(new RoutedEventArgs(FilterClickEvent, sender));
    }
    
  • 在SearchExpView.xaml的DataGrid上监听这个自定义事件:
    <DataGrid local:BlockStyles.FilterClick="DataGrid_FilterClick">
        <!-- 你的列定义 -->
        <Popup x:Name="PopupFiltre" />
    </DataGrid>
    
  • 在SearchExpView.xaml.cs里处理事件,打开弹窗:
    private void DataGrid_FilterClick(object sender, RoutedEventArgs e)
    {
        PopupFiltre.IsOpen = !PopupFiltre.IsOpen;
        // 可选:定位弹窗到触发的Image
        var sourceImage = e.OriginalSource as Image;
        if (sourceImage != null)
        {
            PopupFiltre.PlacementTarget = sourceImage;
            PopupFiltre.Placement = PlacementMode.Bottom;
        }
    }
    

方案3:通过ViewModel控制弹窗状态

如果你的项目遵循MVVM模式,这种方式更符合架构设计:

  • 在ViewModel里添加一个可通知的布尔属性:
    private bool _isFilterPopupOpen;
    public bool IsFilterPopupOpen
    {
        get => _isFilterPopupOpen;
        set
        {
            _isFilterPopupOpen = value;
            OnPropertyChanged();
        }
    }
    
    // 确保ViewModel实现INotifyPropertyChanged接口
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    
  • 在SearchExpView.xaml里绑定Popup的IsOpen属性:
    <Popup x:Name="PopupFiltre" IsOpen="{Binding IsFilterPopupOpen, Mode=TwoWay}" />
    
  • 在BlockStyles.xaml.cs的点击事件里,获取ViewModel并切换状态:
    private void Image_Click(object sender, RoutedEventArgs e)
    {
        var image = sender as Image;
        // 向上查找DataGrid的DataContext(如果Image的DataContext不是ViewModel的话)
        var parentGrid = VisualTreeHelper.GetParent(image) as DataGrid;
        var viewModel = parentGrid?.DataContext as YourViewModelType;
        if (viewModel != null)
        {
            viewModel.IsFilterPopupOpen = !viewModel.IsFilterPopupOpen;
        }
    }
    

内容的提问来源于stack exchange,提问作者Rikube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:15:41