【问题标题】:c# mvvm databind for multiple click events not workingc# mvvm databind 用于多个点击事件不起作用
【发布时间】:2019-07-29 15:38:43
【问题描述】:

我在 c# 中创建了一个 picross 应用程序作为我的第二个 c# 应用程序。 我试图保留它 mvvm。但有一点问题。

我有一个矩形数组,当有人点击这些矩形中的 1 个时,这个矩形的状态需要更改(颜色更改)。

我已经设法以非 mvvm 方式做到这一点,但真正想做的是 mvvm。

所以代码。 首先是 xaml 代码。

<Window x:Class="View.CreatePuzzle"
    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:View"
    xmlns:controls="clr-namespace:View.Controls"
    mc:Ignorable="d"
    Title="CreatePuzzle" Height="450" Width="800">
<Window.Resources>
    <VisualBrush x:Key="myBrush">
        <VisualBrush.Visual>
            <Grid>
                <Rectangle Fill="Red"/>
                <Image Source="Images/backgroundmain.jpg"/>
            </Grid>
        </VisualBrush.Visual>
    </VisualBrush>
</Window.Resources>
<Grid Background="{StaticResource myBrush}" RenderTransformOrigin="0.508,0.819" Height="450" Margin="10,0,10,0">

    <Grid.ColumnDefinitions>

        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="600"/>
    </Grid.ColumnDefinitions>

    <StackPanel>
        <TextBlock Grid.Column="0" Text="your name" />
        <TextBox Grid.Column="0" Text="{Binding Author}" />
    <TextBlock Grid.Column="0" Text="width" />
        <controls:numberinput x:Name="widthfield" Grid.Column="1"  Value="{Binding puzzlewidth}">
        </controls:numberinput>
    <TextBlock Grid.Column="0" Text="height" />
        <controls:numberinput x:Name="heightfield" Grid.Column="0" Value="{Binding puzzleheight}">
        </controls:numberinput>

        <Button Grid.Column="0" Height="25" Content="generate puzzle" 
        Command="{Binding Path=generatefield}"/>
    </StackPanel>

    <controls:PiCrossControl HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" x:Name="picrossControl" ColumnConstraints="{Binding ColumnConstraints}" RowConstraints="{Binding RowRonstraints }" Grid="{Binding Grid}" >
        <controls:PiCrossControl.SquareTemplate>
            <DataTemplate >
                <Rectangle Width="32" Height="32" Stroke="Black" MouseRightButtonDown="Rectangle_MouseRightButtonDown" MouseWheel="Rectangle_MouseWheel">
                    <Rectangle.InputBindings>
                        <MouseBinding Gesture="LeftClick" Command="{Binding Path=Rectangle_MouseLeftButtonDown}"/>
                    </Rectangle.InputBindings>
                    <Rectangle.Fill>
                        <Binding Path="Contents.Value"  UpdateSourceTrigger="PropertyChanged">
                            <Binding.Converter>
                                <local:SquareConverter Empty="White" Filled="Black" Unknown="green" />
                            </Binding.Converter>
                        </Binding>
                    </Rectangle.Fill>
                </Rectangle>
            </DataTemplate>
        </controls:PiCrossControl.SquareTemplate>

    </controls:PiCrossControl>
        <Button Grid.ColumnSpan="2" Height="50" Content="create puzzle" 
        Command="{Binding Path=createpuzzle}" Margin="0,340,0,0"/>
    </Grid>

这里是要取出xaml.cs的方法之一

    private void Rectangle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        Rectangle rectangle = (Rectangle)sender;
        IPlayablePuzzleSquare square = (IPlayablePuzzleSquare)rectangle.DataContext;
       square.Contents.Value = Square.EMPTY;
    }

我想用视图模型方法来替换它:

        public void Rectangle_MouseLeftButtonDown(object sender )
    {
        Debug.WriteLine("leftmousevent in vm");

    }

因此,当我运行此代码时,每个矩形都会出现以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'Rectangle_MouseLeftButtonDown' property not found on 'object' ''PlayablePuzzleSquare' (HashCode=36468595)'. BindingExpression:Path=Rectangle_MouseLeftButtonDown; DataItem='PlayablePuzzleSquare' (HashCode=36468595); target element is 'MouseBinding' (HashCode=10961125); target property is 'Command' (type 'ICommand')

我希望有人可以帮助我。 请注意,我对 c# 很陌生,但有更多的 java 经验。

提前致谢 杰夫·乌伊特霍文

【问题讨论】:

  • 这些对您有帮助吗?

标签: c# wpf mvvm data-binding


【解决方案1】:

如你所说; Rectangle_MouseLeftButtonDown 是一个事件处理程序。

如果没有看到您的视图模型,很难解决这个问题,但是,您应该使用与 Command 按钮绑定相同的结构:

Command="{Binding Path=generatefield}"

所以,在您的视图模型中查找generatefield,然后复制并调整它以替换事件处理程序。

【讨论】:

    【解决方案2】:

    由于您不希望代码落后,您必须从 xaml.cs 中删除鼠标左键单击事件处理程序。 相反,您可以使用 System.Windows.Interactivity.dll 。 首先将此引用添加到您的项目中。然后在 xaml 中添加以下代码。 (示例)

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseLeftButtonDown" >
                <i:InvokeCommandAction Command="{Binding MouseLeftButtonDownClick}"  >
    
                </i:InvokeCommandAction>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Rectangle>
    

    正如您在示例中看到的,我的事件绑定到命令,它位于视图模型中。如果您不熟悉 EventToCommand 绑定,可以通过以下链接了解更多信息

    WPF Binding UI events to commands in ViewModel

    在此之后,您必须在 viewmodel 中实现 ICommand 。 (示例)

    public class ViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public ICommand MouseLeftButtonDownClick { get; }
            public ViewModel()
            {
                MouseLeftButtonDownClick = new RelayCommand(OnMouseLeftButtonClick);
            }
    
            private void OnMouseLeftButtonClick(object obj)
            {
                //Your logic on left button click
            }
    
            public void OnPropertyChanged(string PropName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropName));
            }
        }
    

    我在我的视图模型中使用了 RelayCommand 类,它只是 ICommand 实现。如果您不熟悉 ICommand ,可以从以下链接了解更多信息

    ICommand MVVM implementation

    【讨论】:

    • 您好,答案很好。但是您的命令命名是符合事件。您至少应该在代码 cmets 中解决其命名不正确的问题。
    猜你喜欢
    • 1970-01-01
    • 2016-05-13
    • 2018-06-15
    • 2017-08-22
    • 2012-11-07
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多