Entwickler-Ecke

WPF / Silverlight - Popup Listbox


FrEEzE2046 - Mi 21.04.10 12:52
Titel: Popup Listbox
Hallo,

ich brauche genau so eine Popup Listbox wie man sie vom klassichen MSDN Design kennt.

Beispiel:
http://msdn.microsoft.com/de-de/library/system.windows.media.imagedrawing.aspx

Unter Einstellungen müsst ihr noch klassich wählen. Wenn ihr nun die Maus über System.Windows.Media-Namespace bewegt erscheint die Listbox. Wie kann ich das für meine Silverlight Seite machen?


Kha - Mi 21.04.10 16:24

Unter DropDownButton [http://www.google.com/search?hl=en&q=silverlight+dropdownbutton] sollten sich passende Controls finden lassen :) . Dass sich die Popups automatisch öffnen/schließen, solltest du ja über Events/Blend Behaviors noch nachrüsten können.

Edit: Wahrscheinlich ist es einfacher, direkt ein UserControl aus TextBlock/... und darunter einem Popup zu bauen und das Ganze über Events/Behaviors zu steuern.


FrEEzE2046 - Di 27.04.10 10:38

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Edit: Wahrscheinlich ist es einfacher, direkt ein UserControl aus TextBlock/... und darunter einem Popup zu bauen und das Ganze über Events/Behaviors zu steuern.


Hi,
mir fehlt der richtige Ansatz. Könntest du bitte etwas konkreter werden?


Kha - Di 27.04.10 11:17

So in etwa hatte ich mir das vorgestellt.

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
    <StackPanel>
        <TextBlock MouseEnter="both_MouseEnter"
                   MouseLeave="both_MouseLeave"
                   Background="Gray"
                   x:Name="block">Hello</TextBlock>
        <Popup x:Name="pop"
               MouseEnter="both_MouseEnter"
               MouseLeave="both_MouseLeave">
            <TextBlock Background="Gray">World</TextBlock>
        </Popup>
    </StackPanel>


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
    private void both_MouseEnter(object sender, MouseEventArgs e)
    {
      pop.IsOpen = true;
    }

    private void both_MouseLeave(object sender, MouseEventArgs e)
    {
      pop.IsOpen = false;
    }


FrEEzE2046 - Di 27.04.10 12:56

Hallo,

ich hab da nochmal eine andere Frage. Ein neues UserControl hat ein Text-Property, dass an ein TextBlock-Element weitergereicht werden soll.
Ich habe dafür folgenden Code gefunden:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
public class MyClass : UserControl
{
    public static readonly DependencyProperty TextProperty = 
    DependencyProperty.Register("Text"typeof(string), typeof(DropDownTextBlock), null);

    [BindableAttribute(true)]
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    
    
  public MyClass()
  {
    this._TextBlock.SetBinding
        (
            TextBlock.TextProperty, 
            new Binding() 
            { 
                Source = this
                Path = new PropertyPath("Text"
            }
        );
  }
}


Jetzt stellt sich mir die Frage, warum man nicht einfach folgendes macht:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
public class MyClass : UserControl
{
  public string Text
  {
    get { return this._TextBlock.Text; }
    set { this._TextBlock.Text = value; }
  }
}


Gibt es da einen besonderen Grund?


Kha - Di 27.04.10 13:52

Neue Frage, neues Topic bitte :) . Aber vielleicht genügt dir schon dieser Link, da hast du erst einmal ein wenig zum Lesen ;) : http://msdn.microsoft.com/en-us/library/ms752914.aspx


FrEEzE2046 - Di 27.04.10 14:07

Also ich hätte es jetzt so weit:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
<UserControl x:Class="DropDownTextBlockProject.DropDownTextBlock"
    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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <StackPanel x:Name="LayoutRoot">
        <!-- TextBlock.Text binding is done in code -->
        <TextBlock x:Name="_TextBlock" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave"/>
        <Popup x:Name="_Popup">
            <ListBox x:Name="_ListBox" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave"
                     Width="{Binding ElementName=_TextBlock, Path=ActualWidth}"
                     Background="{Binding ElementName=LayoutRoot, Path=Background}" />
        </Popup>
    </StackPanel>
</UserControl>



C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
public partial class DropDownTextBlock : UserControl
{
    public static readonly DependencyProperty TextProperty = 
        DependencyProperty.Register("Text"typeof(string), typeof(DropDownTextBlock), null);

    [BindableAttribute(true)]
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public ItemCollection Items
    {
        get { return this._ListBox.Items; }
    }

        
    public DropDownTextBlock()
    {
        InitializeComponent();

        this.LayoutRoot.SetBinding
        (
            Panel.BackgroundProperty,
            new Binding()
            {
                Source = this,
                Path = new PropertyPath("Background")
            }
        );
                        
        this._TextBlock.SetBinding
        (
            TextBlock.TextProperty, 
            new Binding() 
            { 
                Source = this
                Path = new PropertyPath("Text"
            }
        );
    }


    private void UserControl_MouseEnter(object sender, MouseEventArgs e)
    {
        this._Popup.IsOpen = true
    }

    private void UserControl_MouseLeave(object sender, MouseEventArgs e)
    {
        this._Popup.IsOpen = false;
    }
}



Das Control ist bei mir aber immer Weiß, egal was ich für einen Background-Wert setze. Woran liegt das?


Kha - Di 27.04.10 15:39

Ich habe deinen Code 1:1 übernommen, mit

XML-Daten
1:
<my:DropDownTextBlock Text="Huh" Background="Red" />                    

bekomme ich auch ein rotes StackPanel und Popup.

Die Bindings kannst du über RelativeSource übrigens auch in XAML setzen. Ich benutze dafür gerne zusätzlich noch den DataContext, falls nicht schon andersweitig verwendet.

XML-Daten
1:
2:
3:
4:
<UserControl ...
    DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <StackPanel x:Name="LayoutRoot" Background="{Binding Background}" ...

Und falls du immer das gleiche Datenmodell durch das UserControl anzeigen lassen willst, sind eigene Dependency Properties eigentlich unnötig, übergib lieber direkt das Model an das UC.


FrEEzE2046 - Di 27.04.10 16:24

Danke für deine Antwort. Also, ich hab das StackPanel jetzt so definiert:

XML-Daten
1:
<StackPanel x:Name="LayoutRoot" Background="{Binding Background}">                    

und dafür das manuelle Binding im Konstruktor entfernt.

Mein UC ist aber immer noch dauerhaft weiß. Hier mein Beispielcode:

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DropDownTextBlockProject;assembly=DropDownTextBlockProject"
  x:Class="DropDownTextBlockTestEnv.MainPage"
  Width="640" Height="480">

  <Grid x:Name="LayoutRoot" Background="White">        
        <local:DropDownTextBlock Text="Dies ist ein Test" Background="Red" Margin="50" FontSize="16" 
                                 HorizontalAlignment="Center" VerticalAlignment="Center"
                                 >
            <local:DropDownTextBlock.Items>
                <TextBlock Text="Hallo"/>
                <TextBlock Text="Hallo"/>
                <TextBlock Text="Hallo"/>
            </local:DropDownTextBlock.Items>
        </local:DropDownTextBlock>
    </Grid>
</UserControl>



Beim string Property "Text" hab ich jedoch keine andere Wahl, als das Ganze im CodeBehind zu machen soweit ich weiß.


Was genau meinst du damit, dass ich eigentlich kein DependencyProperty für meine Daten brauche? Ich hab für die Daten doch die ItemCollection:

C#-Quelltext
1:
2:
3:
4:
public ItemCollection Items
{
  get { return this._ListBox.Items; }
}