24 Stimmen

MVVM + WPF + Popup = ahnungslos

Ich arbeite immer noch an der Änderung meiner bestehenden WPF-Anwendung, um mit dem MVVM-Ansatz "konform" zu sein. Ich bin verdammt nah dran, aber bin nicht sicher, wie man eine der verbleibenden paar Hürden zu lösen.

Ich habe ein GUI-Element (derzeit eine Schaltfläche, obwohl es ein Etikett sein könnte), wo, wenn die Maus es betritt, es das MouseEnter-Ereignis auslöst, und dies erstellt ein Popup in der Code-Behind. Das Popup besteht aus einem einfachen Stackpanel-Layout mit mehreren Schaltflächen. Das Click-Ereignis jeder Schaltfläche ist derzeit dem gleichen Event-Handler zugewiesen, außer dass ich die Tag-Eigenschaft ändern, um einen einfachen (kitschigen) Befehlsparameter zu tun. Ich ringe mit dem "richtigen" Weg, dies in MVVM zu tun, weil die Art, wie ich es jetzt tun ist ziemlich hässlich.

Um dieses Problem zu lösen, denke ich, dass dies die Richtung ist, in die ich gehen sollte, aber ich würde mich über jeden zusätzlichen Beitrag freuen, den Sie mir anbieten können :)

  1. Popup in XAML erstellen. Da mein Popup-Inhalt statisch ist, sollte ich in der Lage sein, das Popup vollständig in XAML zu erstellen. Darüber hinaus würde jede Schaltfläche an dieselbe von ICommand abgeleitete Klasse gebunden werden, z. B.

    <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>
  2. Lassen Sie das Popup über einen Trigger auftauchen, z.B.

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

I denken #Nr. 1 ist in Ordnung, aber mit Nr. 2 habe ich Probleme. Ist dies der richtige Weg, um das Problem anzugehen? Und wenn ja, wie lautet die korrekte XAML-Syntax, um die Eigenschaft IsOpen des Popups auf True zu setzen? Ich konnte keine Beispiele für diese finden.

Wenn mein ganzes Denken fehlerhaft ist, würde ich gerne wissen, welche anderen Möglichkeiten ich habe. Danke!

20voto

Aviad P. Punkte 30713

Hier ist, was ich tun würde, zuerst würde ich meine wiederverwendbaren Teile in Ressourcen zu trennen, und verweisen sie mit ContentControls in XAML. Dies gilt für die Popup sowie an den Button . Da ich mich aber nicht auf eine Schaltfläche beschränken möchte, werde ich eine ContentControl auch dafür:

Die Popup-Vorlage:

<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 Vorlage:

<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>

Im XAML des Hauptfensters würde ich nun folgendes erstellen:

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

Wenn Sie Fragen haben, werde ich sie gerne beantworten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X