Подтвердить что ты не робот

MVVM + WPF + Popup = clueless

Я все еще работаю над тем, чтобы изменить существующее приложение WPF на "совместимый" с подходом MVVM. Я получаю довольно чертовски близко, но не знаю, как решить одно из немногих препятствий.

У меня есть элемент GUI (в настоящее время кнопка, хотя это может быть метка), где, когда мышь входит в нее, она запускает событие MouseEnter, и это создает всплывающее окно с кодом. Всплывающее окно состоит из простой компоновки панели стека с несколькими кнопками. Каждое событие Click Click в данный момент назначается одному и тому же обработчику событий, за исключением того, что я изменяю свойство Tag для выполнения простого (дрянного) параметра команды. Я борюсь с "правильным" способом сделать это в MVVM, потому что способ, которым я сейчас это делаю, довольно уродлив.

Чтобы решить эту проблему, я думаю, что это направление, в котором я должен возглавить, но буду признателен за любые дополнительные материалы, которые вы можете мне предложить.:)

  • Создать всплывающее окно в XAML. Поскольку содержимое Popup является статическим, я должен полностью создать всплывающее окно в XAML. Кроме того, каждая кнопка будет привязана к тому же классу, производному от ICommand. например.

    <Popup x:Key="MyPopup" StaysOpen="False" Placement="Right">
        <Border Background="White" BorderBrush="Black" Padding="5" BorderThickness="2" CornerRadius="5">
            <StackPanel Orientation="Vertical">
                <Button Command="{Binding MyCommand}" CommandParameter="5">5</Button>
                <Button Command="{Binding MyCommand}" CommandParameter="10">10</Button>
                <Button Command="{Binding MyCommand}" CommandParameter="15">15</Button>
                <Button Command="{Binding MyCommand}" CommandParameter="20">20</Button>
            </StackPanel>
        </Border>
    </Popup>
    
  • Создайте всплывающее окно с помощью триггера, например

                            <Button.Triggers>
                                <Trigger Property="Button.IsMouseOver" Value="True">
                                    <Setter TargetName="MyPopup" Property="IsOpen" Value="True" />
                                </Trigger>
                            </Button.Triggers>
    

Я думаю, что № 1 в порядке, но я борюсь с №2. Правильно ли это подходит к проблеме? И если да, то какой правильный синтаксис XAML для того, чтобы установить свойство Popup IsOpen равным True? Я не мог найти примеров для этого.

Если все мое мышление ошибочно, мне бы хотелось услышать, какие у меня другие варианты. Спасибо!

4b9b3361

Ответ 1

Вот что бы я сделал, сначала я бы отделил свои многоразовые части от ресурсов и ссылался на них с помощью ContentControls в XAML. Это относится к Popup, а также к Button. Однако я не хочу ограничивать себя только кнопкой, поэтому я буду использовать ContentControl для этого:

Шаблон всплывающего окна:

<ControlTemplate x:Key="PopupTemplate">
    <Border 
                Background="White" 
                BorderBrush="Black" 
                Padding="5" 
                BorderThickness="2" 
                CornerRadius="5">
        <StackPanel Orientation="Vertical">
            <Button Command="{Binding MyCommand}" 
                            CommandParameter="5">5</Button>
            <Button Command="{Binding MyCommand}" 
                            CommandParameter="10">10</Button>
            <Button Command="{Binding MyCommand}" 
                            CommandParameter="15">15</Button>
            <Button Command="{Binding MyCommand}" 
                            CommandParameter="20">20</Button>
        </StackPanel>
    </Border>
</ControlTemplate>

Шаблон ContentControl:

<ControlTemplate x:Key="MyControlTemplate" TargetType="ContentControl">
    <Grid Name="MyControl">
        <ContentPresenter Content="{TemplateBinding Content}"/>
        <Popup Name="MyPopup" StaysOpen="True" Placement="Bottom">
            <ContentControl Template="{StaticResource PopupTemplate}"/>
        </Popup>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger SourceName="MyControl" 
                 Property="UIElement.IsMouseOver" 
                 Value="True">
            <Setter TargetName="MyPopup" 
                    Property="Popup.IsOpen" 
                    Value="True"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Теперь в главном окне XAML я создам следующее:

<ContentControl Template="{StaticResource MyControlTemplate}">
    <Button Content="Test"/>
</ContentControl>

Если у вас есть какие-либо вопросы, я с удовольствием отвечу.