none
UserControl Event hinzufügen RRS feed

  • Frage

  • wie kann dem Usercontrol -> Button1 bzw. Button2 ein individuelles Event hinzugefügt werden wenn sich das UserControl im  Window befindet?

    <UserControl x:Class="UserControl1"
                 x:Name="UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d"
                 xmlns:mycontrol="clr"
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <Button Content="Button1" Name="Button1"/>
            <Button Content="Button2" Name="Button2"/>
        </Grid>
    <Window x:Class="MainWindow"
            x:Name="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mycontrol="clr-namespace:WpfApplication1"   
        Title="MainWindow" Height="350" Width="525">
        
        
        <Grid>
            <mycontrol:UserControl1 x:Name="UserControl11"/>
                </Grid>
    </Window>



    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Montag, 9. April 2018 20:29

Antworten

  • Hi Thomas,
    im Falle einer Befehlsschaltfläche im UnserControl brauchst Du kein Ereignis hinzuzufügen. Es reicht, die Bindung an die Comand-Eigenschaft von "außen" zu gewährleisten. Hier mal eine Demo.

    XAML des UserControls. Die Befehlsschaltfläche ist an eine DependencyProperty des UserControls mit dem Context des UserControls gebunden:

    <UserControl x:Class="Window29UC1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                 x:Name="uc">
      <Grid>
        <Button Content="Befehlsschaltfläche im UserControl" Command="{Binding UcCommand, ElementName=uc}"/>
      </Grid>
    </UserControl>

    Dazu der CodeBehind mit der DependencyProperty:

    Public Class Window29UC1
    
      Public Shared ReadOnly UcCommandProperty As DependencyProperty =
            DependencyProperty.Register("UcCommand", GetType(ICommand), GetType(Window29UC1))
    
      Public Property UcCommand As ICommand
        Get
          Return CType(GetValue(UcCommandProperty), ICommand)
        End Get
        Set(value As ICommand)
          SetValue(UcCommandProperty, value)
        End Set
      End Property
    
    End Class


    Das UserControl wird dann im Fenster eingesetzt. In der konkreten Demo befindet sich das UserControl in einer Bibliothek, was sehr zu empfehlen ist. UserControls im gleichen Projekt wie die Fenster kann viel Stress bedeuten.

    XAML des Fensters:

    <Window x:Class="Window29"
            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:WpfApp1"
            xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            mc:Ignorable="d"
            Title="Window29" Height="300" Width="300">
      <Window.Resources>
        <local:Window29VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <uc:Window29UC1 UcCommand="{Binding Cmd}"/>
      </Grid>
    </Window>

    Und der ViewModel dazu:

    Public Class Window29VM
      Public ReadOnly Property Cmd As ICommand
        Get
          Return New RelayCommand(AddressOf CmdExec)
        End Get
      End Property
    
      Private Sub CmdExec(obj As Object)
        MsgBox("Befhelsschaltfläche im UserControl ausgelöst")
      End Sub
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort vorgeschlagen Peter Fleischer Dienstag, 10. April 2018 07:44
    • Als Antwort markiert Thomas2705 Dienstag, 10. April 2018 09:14
    Dienstag, 10. April 2018 07:25
  • Hi Thomas,
    UserControls im gleichen Projekt wie die Fenster (Windows), in denen die UserControls genutzt werden, zu halten, ist nicht gut. Auch das Halten die UserControls in einem Ordner im gleichen Projekt bedeutet, dass es sich in der gleichen Assembly befindet. Wenn z.B. ein Fehler im UserControl die erfolgreiche Übersetzung verhindert, kann auch der Designer für das Fenster (Window) nicht erfolgreich ausgeführt werden.

    Wenn jedoch die UserControls in einem eigenen Projekt gehalten werden und es mindestens einmal eine erfolgreiche Übersetzung gab, dann kann der Designer für das Fenster im Hauptprojekt auch erst einmal arbeiten, ohne dass er wegen Fehler im eigenen Projekt die Anzeige verweigert. Erst, wenn das Projekt mit dem UserControl das nächste Mal erfolgreich (ohne Fehler) übersetzt wurde, wird diese neue Assembly auch im Hauptprojekt genutzt.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Dienstag, 10. April 2018 09:14
    Dienstag, 10. April 2018 07:43
  • Hi Thomas,
    für jede fremde Assembly (dll), die im Projekt genutzt wird, ist ein Verweis auf die Assembly hinzuzufügen. Das betrifft auch die Nutzung einer Bibliothek mit UserControls, die sich z.B. in einem weiteren Projekt in der Projektmappe mit dem "Hauptprojekt" befinden.

    Weiterhin ist in der Datei (Programmcode bzw. XAML), in der das UserControl genutzt wird, ein Verweis auf den genutzten Namensraum zu hinterlegen, wenn nicht mit vollqualifiziertem Namensraum gearbeitet werden soll. Im Programmcode ist dazu die using-Anweisung mit dem vollständigen Namensraum zu Beginn des Programmcodes zu nutzen. Im XAML ist ein xmlns-Attribut mit dem vollständigen Namensraum und dem Namen der Assembly zu nutzen. Beim Hinzufügen des xmlns-Attributes zeigt die IntelliSense alle Möglichkeiten an. Basis dazu sind die Projektverweise.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Donnerstag, 26. April 2018 07:17
    Donnerstag, 26. April 2018 04:52
  • Hi Thomas,
    ein UserControl kapselt Funktionalitäten. Über Eigenschaften des UserControls oder auch des an das UserControl gebundene ViewModel können die Funktionalitäten parametriert werden. Das bedeutet, dass die Logik für das UserControl in Abhängigkeit von äußeren Parameterwerten verzweigen kann. Solch ein äußerer Parameterwert kann beispielsweise eine Information zum Platz sein, die dem UserControl "mitgeteilt" wird.

    Z.B. uc wurde in WinA und WinB eingefügt. Beim Ereignis auf uc in WinA wird die MessageBox.Show "WinA" ausgeführt. Beim Ereignis in WinB wird die MessageBox.Show "WinB" ausgeführt.

    Hier könnte das UserControl z.B. eine DependencyProperty erhalten, der ein String ("WinA" oder "WinB") übergeben wird. In der Logik des UserControls wird einfach in einer if-Anweisung auf "WinA" und auf "WinB" geprüft. Den Wert der DependencyProperty des UserControls kann man über Element-Bindung auch an den Namen des Fensters binden, in dem sich das UserControl befindet.

    Eine solche Lösung ist aber nicht gut, da immer auf feste Bezeichner geprüft wird und in anderen Einsatzfällen dann die Kapsel (UserControl) nicht ohne Anpassungen einsetzbar ist.

    Besser ist es, die Logik universell zu gestalten (unabhängig vom Namen des Platzes / Fensters), sondern über festlegte Bezeichner (z.B. Aufzählung) oder, wenn das nicht möglich ist, einen Converter einzusetzen.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Donnerstag, 26. April 2018 07:56
    Donnerstag, 26. April 2018 07:51

Alle Antworten

  • Hi Thomas,
    im Falle einer Befehlsschaltfläche im UnserControl brauchst Du kein Ereignis hinzuzufügen. Es reicht, die Bindung an die Comand-Eigenschaft von "außen" zu gewährleisten. Hier mal eine Demo.

    XAML des UserControls. Die Befehlsschaltfläche ist an eine DependencyProperty des UserControls mit dem Context des UserControls gebunden:

    <UserControl x:Class="Window29UC1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                 x:Name="uc">
      <Grid>
        <Button Content="Befehlsschaltfläche im UserControl" Command="{Binding UcCommand, ElementName=uc}"/>
      </Grid>
    </UserControl>

    Dazu der CodeBehind mit der DependencyProperty:

    Public Class Window29UC1
    
      Public Shared ReadOnly UcCommandProperty As DependencyProperty =
            DependencyProperty.Register("UcCommand", GetType(ICommand), GetType(Window29UC1))
    
      Public Property UcCommand As ICommand
        Get
          Return CType(GetValue(UcCommandProperty), ICommand)
        End Get
        Set(value As ICommand)
          SetValue(UcCommandProperty, value)
        End Set
      End Property
    
    End Class


    Das UserControl wird dann im Fenster eingesetzt. In der konkreten Demo befindet sich das UserControl in einer Bibliothek, was sehr zu empfehlen ist. UserControls im gleichen Projekt wie die Fenster kann viel Stress bedeuten.

    XAML des Fensters:

    <Window x:Class="Window29"
            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:WpfApp1"
            xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            mc:Ignorable="d"
            Title="Window29" Height="300" Width="300">
      <Window.Resources>
        <local:Window29VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <uc:Window29UC1 UcCommand="{Binding Cmd}"/>
      </Grid>
    </Window>

    Und der ViewModel dazu:

    Public Class Window29VM
      Public ReadOnly Property Cmd As ICommand
        Get
          Return New RelayCommand(AddressOf CmdExec)
        End Get
      End Property
    
      Private Sub CmdExec(obj As Object)
        MsgBox("Befhelsschaltfläche im UserControl ausgelöst")
      End Sub
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort vorgeschlagen Peter Fleischer Dienstag, 10. April 2018 07:44
    • Als Antwort markiert Thomas2705 Dienstag, 10. April 2018 09:14
    Dienstag, 10. April 2018 07:25
  • Hallo Peter

    Zunächst vielen Dank für Deine Antwort.

    Ich nehme an "In der konkreten Demo befindet sich das UserControl in einer Bibliothek..." meinst Du einen separaten Ordner im  Projekt? (Ich habe für alle (zuküftigen) UserControls einen separaten Ordner "UserControls" im Projekt.


    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Dienstag, 10. April 2018 07:32
  • Hi Thomas,
    UserControls im gleichen Projekt wie die Fenster (Windows), in denen die UserControls genutzt werden, zu halten, ist nicht gut. Auch das Halten die UserControls in einem Ordner im gleichen Projekt bedeutet, dass es sich in der gleichen Assembly befindet. Wenn z.B. ein Fehler im UserControl die erfolgreiche Übersetzung verhindert, kann auch der Designer für das Fenster (Window) nicht erfolgreich ausgeführt werden.

    Wenn jedoch die UserControls in einem eigenen Projekt gehalten werden und es mindestens einmal eine erfolgreiche Übersetzung gab, dann kann der Designer für das Fenster im Hauptprojekt auch erst einmal arbeiten, ohne dass er wegen Fehler im eigenen Projekt die Anzeige verweigert. Erst, wenn das Projekt mit dem UserControl das nächste Mal erfolgreich (ohne Fehler) übersetzt wurde, wird diese neue Assembly auch im Hauptprojekt genutzt.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Dienstag, 10. April 2018 09:14
    Dienstag, 10. April 2018 07:43
  • D.h. also ich erstelle für alle UserControls ein eigenes Projekt; ein Projekt in dem alle UserControls abgelegt werden.

    Wie bekomme ich dann die UserControls aus Projekt A in das eigentliche Projekt B mit den Fenstern? Wie nennt man das wonach ich suchen muß?


    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Dienstag, 10. April 2018 09:14
  • Hi Thomas,
    am einfachsten ist es, in einer Projektmappe beide Projekte (Projekt mit Fenstern und Bibliotheksprojekt mit UserControls) zu halten. Im Hauptprojekt (Projekt mit Fenstern) ist lediglich ein Verweis auf das Bibliotheksprojekt hinzuzufügen. Überall, wo auf die UserControls zuzugreifen ist, muss dann ein Imports (wenn im Code) oder ein entsprechendes xmlns (wenn im XAML) hinzugefügt werden.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Dienstag, 10. April 2018 09:38
  • " lediglich ein Verweis auf das Bibliotheksprojekt hinzuzufügen"

    Ist es richtig dass ich dann für jedes Control in der Bibliothek einen extra Verweis erstellen muß?


    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Mittwoch, 25. April 2018 20:24
  • Hi Thomas,
    für jede fremde Assembly (dll), die im Projekt genutzt wird, ist ein Verweis auf die Assembly hinzuzufügen. Das betrifft auch die Nutzung einer Bibliothek mit UserControls, die sich z.B. in einem weiteren Projekt in der Projektmappe mit dem "Hauptprojekt" befinden.

    Weiterhin ist in der Datei (Programmcode bzw. XAML), in der das UserControl genutzt wird, ein Verweis auf den genutzten Namensraum zu hinterlegen, wenn nicht mit vollqualifiziertem Namensraum gearbeitet werden soll. Im Programmcode ist dazu die using-Anweisung mit dem vollständigen Namensraum zu Beginn des Programmcodes zu nutzen. Im XAML ist ein xmlns-Attribut mit dem vollständigen Namensraum und dem Namen der Assembly zu nutzen. Beim Hinzufügen des xmlns-Attributes zeigt die IntelliSense alle Möglichkeiten an. Basis dazu sind die Projektverweise.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Donnerstag, 26. April 2018 07:17
    Donnerstag, 26. April 2018 04:52
  • Danke


    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Bei Deinem o.g. Beispiel führt ein UserControl (uc) genau eine bestimmte Aktion durch. Wenn das UserControl allerdings in Abhängigkeit vom Platz (Fenster) in dem es gerade eingebettet wurde abhängige Ereignis ausführen soll... was ist dann?

    Z.B. uc wurde in WinA und WinB eingefügt. Beim Ereignis auf uc in WinA wird die MessageBox.Show "WinA" ausgeführt. Beim Ereignis in WinB wird die MessageBox.Show "WinB" ausgeführt.

    Prüft das Command vor Ausführung die Abhängigkeit (WinA oder WinB) des Ereignisses? Wenn es so ist; wie könnte es geprüft werden; z.B. die Abhängigkeit von x:Name des Fensters (If x:name="WinA" Then dann ...)

    • Bearbeitet Thomas2705 Donnerstag, 26. April 2018 07:29
    Donnerstag, 26. April 2018 07:17
  • Hi Thomas,
    ein UserControl kapselt Funktionalitäten. Über Eigenschaften des UserControls oder auch des an das UserControl gebundene ViewModel können die Funktionalitäten parametriert werden. Das bedeutet, dass die Logik für das UserControl in Abhängigkeit von äußeren Parameterwerten verzweigen kann. Solch ein äußerer Parameterwert kann beispielsweise eine Information zum Platz sein, die dem UserControl "mitgeteilt" wird.

    Z.B. uc wurde in WinA und WinB eingefügt. Beim Ereignis auf uc in WinA wird die MessageBox.Show "WinA" ausgeführt. Beim Ereignis in WinB wird die MessageBox.Show "WinB" ausgeführt.

    Hier könnte das UserControl z.B. eine DependencyProperty erhalten, der ein String ("WinA" oder "WinB") übergeben wird. In der Logik des UserControls wird einfach in einer if-Anweisung auf "WinA" und auf "WinB" geprüft. Den Wert der DependencyProperty des UserControls kann man über Element-Bindung auch an den Namen des Fensters binden, in dem sich das UserControl befindet.

    Eine solche Lösung ist aber nicht gut, da immer auf feste Bezeichner geprüft wird und in anderen Einsatzfällen dann die Kapsel (UserControl) nicht ohne Anpassungen einsetzbar ist.

    Besser ist es, die Logik universell zu gestalten (unabhängig vom Namen des Platzes / Fensters), sondern über festlegte Bezeichner (z.B. Aufzählung) oder, wenn das nicht möglich ist, einen Converter einzusetzen.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert Thomas2705 Donnerstag, 26. April 2018 07:56
    Donnerstag, 26. April 2018 07:51
  • "sondern über festlegte Bezeichner (z.B. Aufzählung)" D.h. ein Bezeichner im eingebetten Usercontrol ähnlich dem x:Name?

    Es geht mir um WPF(XAML) Visual Studio Proff. 2010, VisualBasic, Win7 und verständliche Hilfe. Als Quelle nutze ich oft msdn Hilfe.

    Donnerstag, 26. April 2018 07:56
  • "sondern über festlegte Bezeichner (z.B. Aufzählung)" D.h. ein Bezeichner im eingebetten Usercontrol ähnlich dem x:Name

    Hi Thomas,
    nein, so meine ich das nicht!

    Die Logik im UserControl erfordert nach Deinen Beschreibungen eine Verzweigung des für das UserControl verantwortlichen Codes. Diese Verzweigung entspricht der zu implementierenden Geschäftslogik. D.h. es gibt z.B. einen Geschäftsfall "X", bei dessem Vorliegen der erste Programmzweig abzuarbeiten ist und einen Geschäftsfall "Y", bei dem der zweite Programmzweig abzuarbeiten ist. Dem UserControl ist es egal, welcher konkrete Geschäftsfall vorliegt. Wichtig ist nur, dass beide Geschäftsfälle unterstützt werden. Um dem UserControl mitzuteilen, welcher Geschäftsfall zu bearbeiten ist, bekommet das UserControl eine öffentliche Eigenschaft. Damit der zu übergebende Wert aber unabhängig ist z.B. vom konkreten Platz / Fenster und deren Bezeichnern, kann eine im Projekt enthaltene Aufzählung abstrakter Werte genutzt werden. Die Aufzählung hat z.B. zwei Werte: X und Y. Der Programmierer entscheidet dann beim Einsatz des UserControl, ob Geschäftsfall "X oder "Y" am konkreten Platz anzuwenden ist.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 26. April 2018 08:16