WPF的listview的问题。 如何实现鼠标移动到某一行,该行中的button列的button的属性设为Visible(可见)。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF的listview的问题。 如何实现鼠标移动到某一行,该行中的button列的button的属性设为Visible(可见)。相关的知识,希望对你有一定的参考价值。

listview中定义几个列,其中一列是button button的默认是不可见的,其余是数据列。
listview的itemSource是一个自定义类型的对象list。
所有的listviewitem都是通过绑定自定义对象的属性自动生成的。
问题是,如何实现鼠标移动到某一行,该行中的button列的button的属性设为Visible(可见)。
我的想法是将button的visibility属性与lisviewitem的isMouseOver属性建立绑定。但不知如何实现。
主要lisitviewitem是自动生成的。。。所以不好弄。
有说的不明白的地方大家尽管提

参考技术A 我给你点建议,你定义一个Item模版,然后增加一个Button列,这个Button的可见性和Item模版的触发器关联,这样就可以了! 参考技术B if (e.Item.ItemType == ListViewItemType.DataItem)

(e.Item.FindControl("Tr") as htmlTableRow).Attributes.
Add("onmouseover", "method1()");
(e.Item.FindControl("Tr") as HtmlTableRow).Attributes.
Add("onmouseout", "method2()");


method1()和method2()方法,就是你显示和隐藏按钮的方法。追问

1.你这段代码准备放在哪里?listview的哪个事件的处理函数里?
2.e代表?eventargs?
2."Tr"什么意思

参考技术C 可以看看listview中是否有生成行的处理事件,可以在这个事件中处理button的可见性,我记得datagridview中有生成行的处理函数。

如何实现一个由鼠标移动的 WPF 控件,如滑块控件但 2D?

【中文标题】如何实现一个由鼠标移动的 WPF 控件,如滑块控件但 2D?【英文标题】:How to implement a WPF control that is moved by the mouse, like a slider control but 2D? 【发布时间】:2021-12-27 22:24:05 【问题描述】:

我想通过其控制点 Q(Segment 的 Point1 属性)在运行时控制 QuadraticBezierSegment 的呈现。我可以使用单独的滑块控件来控制点的 X 和 Y 值。但我最终希望能够使用拖动控制点来重塑段。在下面的代码中,我可以绘制控制点和线段,它们都响应滑块。但我不知道如何拖动点来控制段(然后我会放弃滑块)。

目前没有后面的代码,我正在尝试将所有内容保存在 XAML/MVVM 中,但不确定这是否可能。谢谢。

这是视图模型:

namespace BezierDemo

class MainViewModel : INotifyPropertyChanged

    private System.Windows.Point _q;

    private double _qy;
    private double _qx;

    public MainViewModel()
    
        _q.X = 50;
        _q.Y = 0;
    

    // https://www.danrigby.com/2015/09/12/inotifypropertychanged-the-net-4-6-way/

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    
        if (Equals(storage, value))
        
            return false;
        

        storage = value;
        this.OnPropertyChanged(propertyName);
        return true;
    

    public double QX
    
        get  return _q.X; 
        set  Q = new System.Windows.Point(value, Q.Y); SetProperty(ref this._qx, value); 

    

    public double QY
    
        get  return _q.Y; 
        set  Q = new System.Windows.Point(Q.X, value); SetProperty(ref this._qy, value); 
    

    public System.Windows.Point Q
    
        get  return _q; 
        set  SetProperty(ref this._q, value); 
    


...这里是 XAML:

<Window x:Class="BezierDemo.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:local="clr-namespace:BezierDemo"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="506">
<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>
<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="400*"/>
        <ColumnDefinition Width="100*"/>
    </Grid.ColumnDefinitions>

    <!-- Bezier Control Point -->
    <Canvas Grid.Column="0">
        <Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" Cursor="Hand" >
            <Ellipse.RenderTransform>
                <TranslateTransform X="Binding Path=QX" Y="Binding Path=QY"/>
            </Ellipse.RenderTransform>
            <Ellipse.Triggers>
                <EventTrigger RoutedEvent="Ellipse.MouseMove">

                </EventTrigger>
            </Ellipse.Triggers>
        </Ellipse>
    </Canvas>

    <!-- QuadraticBezierSegment -->
    <Path Stroke="Black" Fill="Gray" Grid.Column="0">
        <Path.Data>
            <PathGeometry>
                <PathFigure>
                    <PathFigure.StartPoint>
                        <Point X="0" Y="100" />
                    </PathFigure.StartPoint>
                    <QuadraticBezierSegment Point1="Binding Path=Q" Point2="100, 100" />
                </PathFigure>
            </PathGeometry>
        </Path.Data>
    </Path>

    <!-- X & Y Slider Controls -->
    <Grid Grid.Column="2" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0" VerticalAlignment="Center">
            <Slider Name="X" Orientation="Vertical" Maximum="100" HorizontalAlignment="Center" VerticalAlignment="Center" Height="234" Value="Binding Path=QX" Minimum="0.0"/>
            <Label HorizontalAlignment="Center">X</Label>
        </StackPanel>
        <StackPanel Grid.Column="1" VerticalAlignment="Center">
            <Slider Name="Y" Orientation="Vertical" Maximum="100" HorizontalAlignment="Center" VerticalAlignment="Center" Height="234" Value="Binding Path=QY" Minimum="0.0"/>
            <Label HorizontalAlignment="Center">Y</Label>
        </StackPanel>
    </Grid>

</Grid>

【问题讨论】:

将 MouseMove 处理程序添加到设置 Ellipse 位置的 Canvas。画布需要具有非空背景,即透明。通过 Canvas.Left 和 Top 而不是 RenderTransform 设置位置。 请注意,在视图模型中实现 x/y 值的双重存储似乎毫无意义。存储 x 和 y,或点,而不是两者。 如果用户可以快速移动鼠标,你会发现他们失去了一个“拇指”,不得不回去重新拿起它。正是出于这个原因,我制作了可拖动的用户控件,并在它们的包含面板中处理预览鼠标向下、移动和鼠标向上以获取可拖动的东西。 【参考方案1】:

如果您将贝塞尔控制点包装在 Thumb 元素中,那么您可以很容易地完成您想要的。

<!-- Bezier Control Point -->
<Canvas Grid.Column="0">
    <Thumb DragDelta="Thumb_DragDelta" Canvas.Left="Binding QX, Mode=TwoWay" Canvas.Top="Binding QY, Mode=TwoWay">
        <Thumb.Template>
            <ControlTemplate>
               <Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" />
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>
</Canvas>

注意:我必须将 Panel.ZIndex="-1" 添加到 QuadraticBezierSegment 中,这样椭圆才能呈现在 Bezier 段的前面。或者您可以在贝塞尔线段声明之后移动拇指部分。

代码隐藏:

private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)

    UIElement thumb = e.Source as UIElement;

    Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
    Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);

您可以使用Microsoft.Xaml.Behaviors.Wpf nuget 包将后面的代码转换为视图模型中的事件处理程序。

应该是这样的

<Canvas Grid.Column="0">
    <Thumb Canvas.Left="Binding QX, Mode=TwoWay" Canvas.Top="Binding QY, Mode=TwoWay">
        <b:Interaction.Triggers>
            <b:EventTrigger EventName="DragDelta">
                <b:InvokeCommandAction Command="Binding HandleDragDelta" PassEventArgsToCommand="True" />
            </b:EventTrigger>
        </b:Interaction.Triggers>
        <Thumb.Template>
            <ControlTemplate>
                <Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" />
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>
</Canvas>

其中HandleDragDelta 是某种ICommand 实现,它可以采用DragDeltaEventArgs 参数,因为您需要它。

private DelegateCommand<DragDeltaEventArgs> handleDragDelta;
public ICommand HandleDragDelta => handleDragDelta ??= new DelegateCommand<DragDeltaEventArgs>(PerformHandleDragDelta);

private void PerformHandleDragDelta(DragDeltaEventArgs e)

    UIElement thumb = e.Source as UIElement;

    Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
    Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);

【讨论】:

谢谢,Thumb 正是我想要的。我还没有让事件处理程序工作 - DelegateCommand 需要 Prism 吗?但能够移动拇指是拼图中缺失的部分。 可以是棱镜。那里有许多 ICommand 实现。如果您不想使用 Prism,请参阅 gist.github.com/InKahootz/0fb62ad9330c07aec2f89a34e3c3e5a4 以获得简单的方法。一旦你连接了事件处理程序,它应该开始移动/可拖动!

以上是关于WPF的listview的问题。 如何实现鼠标移动到某一行,该行中的button列的button的属性设为Visible(可见)。的主要内容,如果未能解决你的问题,请参考以下文章

WPF:如何在拖动 ListView 项目时允许在 ListView 中使用鼠标滚轮滚动?

如何实现一个由鼠标移动的 WPF 控件,如滑块控件但 2D?

在WPF里面实现以鼠标位置为中心缩放移动图片

WPF--鼠标右键菜单中的Command命令实现

WPF C# 实现鼠标穿透窗体

wpf ListView DataTemplate方式的鼠标悬停和选中更改背景色