Для школы я должен сделать пользовательский интерфейс WPF в С#, код домена уже сделан учителем. мне нужно обрабатывать события щелчка на прямоугольнике, я решил обернуть прямоугольник вокруг кнопки. вот часть моего xaml, где я делаю прямоугольник

<Window x:Class="View.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:ViewModel;assembly=ViewModel"
    xmlns:controls="clr-namespace:View.Controls"
    mc:Ignorable="d"
    x:Name="Picross"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <controls:PiCrossControl x:Name="picrossControl" Margin="0,0,10.2,-0.2" Grid="{Binding Grid}" RowConstraints="{Binding RowConstraints}" ColumnConstraints="{Binding ColumnConstraints}">
        <controls:PiCrossControl.SquareTemplate x:Uid="rect">
            <DataTemplate>
                <Button Command="{Binding Path=DataContext.OnClick, ElementName=Picross}">
                    <Rectangle IsHitTestVisible="False" Width="40" Height="40" Stroke="Black" Grid.Column="0" StrokeThickness="2">
                        <Rectangle.Fill>
                            <Binding Path="Contents.Value">
                                <Binding.Converter>
                                    <local:SquareConverter Empty="White" Filled="#123456" Unknown="Gray"/>
                                </Binding.Converter>
                            </Binding>
                        </Rectangle.Fill>
                    </Rectangle>
                </Button>
            </DataTemplate>
        </controls:PiCrossControl.SquareTemplate>
        <controls:PiCrossControl.RowConstraintsTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding Values}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Width="40" Height="40" Text="{Binding Value}" TextAlignment="Center" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </controls:PiCrossControl.RowConstraintsTemplate>
        <controls:PiCrossControl.ColumnConstraintsTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding Values}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Vertical" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Width="40" Height="40" Text="{Binding Value}" TextAlignment="Center" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </controls:PiCrossControl.ColumnConstraintsTemplate>
    </controls:PiCrossControl>
    <Button Grid.Column="1" Width="150" Height="20" Command="{Binding CheckSolution}">
        <TextBlock Text="check solution"/>
    </Button>
</Grid>

Привязка OnClick почему-то не прописывается. вот мой контекст данных xaml

public class GameModel
{
    private IPlayablePuzzle PlayablePuzzle;

    public GameModel()
    {
        var puzzle = Puzzle.FromRowStrings("xxxxx", "x...x", "x...x", "x...x", "xxxxx");
        var facade = new PiCrossFacade();
        this.PlayablePuzzle = facade.CreatePlayablePuzzle(puzzle);
        //Console.WriteLine(string.Join("\n", PlayablePuzzle.RowConstraints.Items.Select(x=>x.ToString())));
        //var vmGrid = this.PlayablePuzzle.Grid.Map(square => new SquareViewModel(square)).Copy();
        this.CheckSolution = new CheckSolution(PlayablePuzzle);
        this.OnClick = new OnClick();
    }
    public IGrid<IPlayablePuzzleSquare> Grid => PlayablePuzzle.Grid;
    public IEnumerable<IPlayablePuzzleConstraints> RowConstraints => this.PlayablePuzzle.RowConstraints;
    public IEnumerable<IPlayablePuzzleConstraints> ColumnConstraints => this.PlayablePuzzle.ColumnConstraints;

    public string Test => "Test";
    #region Commands 
    public ICommand CheckSolution { get; }
    public ICommand OnClick { get; }
    #endregion
}

Как вы можете видеть, у меня есть 2 контрольных решения ICommands, которые также привязаны к кнопке в моем xaml, и эта кнопка работает (она не обернута вокруг прямоугольника, это просто кнопка, обернутая вокруг текстового блока) ICommand OnClick привязан к моему кнопка прямоугольник. вот мой код OnClick

public class OnClick : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        Console.WriteLine(parameter);
    }
}

Обновление: я установил имя окна на пикросс и обновил свою привязку к кнопке, и теперь получаю следующую ошибку: Ошибка System.Windows.Data: 4: не удается найти источник для привязки со ссылкой «Имя элемента = Пикросс». BindingExpression:Path=DataContext.OnClick; Элемент данных = ноль; целевой элемент — «Кнопка» (Name=''); целевое свойство — «Команда» (тип «ICommand»)

-1
rafaelBackx 1 Апр 2020 в 16:44
Где вы устанавливаете свой DataContext?
 – 
Jonathan Alfaro
1 Апр 2020 в 21:39
Ваш код выглядит так, как будто он должен работать, если GameModel действительно является контекстом GameModel. Как вы думаете, почему это не так? Вы проверили окно вывода? Вы установили точку останова в OnClick.Execute и запустили приложение в режиме отладки?
 – 
BionicCode
1 Апр 2020 в 22:46
1
Я исправил свою проблему, используя решение из этого поста 9122592/…
 – 
rafaelBackx
2 Апр 2020 в 00:31
1
Я знаю. Но он связывается с помощью Binding.Elementname. Это будет работать, если DataTemplate определен в пределах именованного элемента управления.
 – 
BionicCode
2 Апр 2020 в 01:30
1
Согласовано.
 – 
Jonathan Alfaro
2 Апр 2020 в 03:55

1 ответ

Это происходит потому, что команда привязывается из DataTemplate. Вам нужно будет «вернуться» к родителю, чтобы найти контекст данных.

Что-то вроде этого:

Command="{Binding Path=DataContext.OnClick, ElementName=MainWindowName}"

В этом примере я предполагаю, что вы установили GameModel как DataContext окна с именем «MainWindowName».

Таким образом, вы можете добавить свое имя в свое окно следующим образом:

x:Name="MainWindowName"

Вы можете назначить свой контекст данных в конструкторе окна следующим образом:

    public MainWindow()
    {
      InitializeComponent();
      DataContext = new GameModel();
    }

Это связывание может быть выражено другими способами.

Другой способ сделать это — использовать ссылку следующим образом:

Command="{Binding Path=DataContext.OnClick, Source={x:Reference picrossControl}}"
0
Jonathan Alfaro 2 Апр 2020 в 01:07
Я только что опубликовал свой полный xaml
 – 
rafaelBackx
1 Апр 2020 в 21:35
Я добавил «Picross» в качестве имени окна, и когда я использую его в кнопке, я получаю следующую ошибку System.Windows.Data Error: 4: не удается найти источник для привязки со ссылкой «ElementName = Picross». BindingExpression:Path=DataContext.OnClick; Элемент данных = ноль; целевой элемент — «Кнопка» (Name=''); целевое свойство — «Команда» (тип «ICommand»)
 – 
rafaelBackx
1 Апр 2020 в 22:50