WPF ItemsControl

WPF ItemsControl
2007-02-27T17:04:05+01:00
2007-04-03T12:46:51+02:00
2022-11-04T01:50:40+01:00
wjuszko
Sziasztok. Ujbol egy WPF-es problemam van
Csinaltam egy osztalyt ami egy ObservableCollection<StackPanel> be pakolgat bele cuccokat. ItemsControl segitsegevel szeretnem a benne levo StackPaneleket megjeleniteni, valhogy igy:

<ItemsControl Name="NyelvValasztasa" ItemsSource="{Binding Source={StaticResource NyelvValasztas}}" Margin="20,20,20,20" > <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15"> <ItemsPresenter/> </Border> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Name="wrap" MouseLeftButtonUp="NyelvValasztasClick"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl>

A problema az, hogy a MouseLeftButtonUp esemeny a WrapPanel-hez kerul, nem pedig az egyes StackPanel-ekhez amik a O.Collection-ban vannak. Tud valaki valami okossagot amit en nem?
Mutasd a teljes hozzászólást!
Nem. Például a template VisualTree tulajdonsága is null, ha XAML-ből állítja elő a rendszer, pedig ez lenne az a tulajdonság, ahol hozzáférhetnél ahhoz, hogy mi legyen a template tartalma. Nézd meg a Quick Watch-ben, ha nem hiszed el. Csak a nem publikus Optimized verzió érhető el, ha XAML-ből használod. Ugyan így nem tudsz belemenni az ItemsControl tartalmába sem. Ez rég nem WinForms, ahol csak úgy turkálni lehetet a vezérlők tartalmában. Ezt is megnézheted a Quick Watch-ben! Csupa olyan helyen van a tulajdonképpeni tartalom, ami nem publikus, és nem is eredeti, hanem valami optimalizált formában.

De még mindig nem értem a problémád!!! Annyira túl akarod bonyolítani, hogy az nem igaz. Van már egy handlered a stuff_Click-hez, right? Akkor meg mi a gond? Át akarod definiálni? Tégy ki a Window-nak egy publikus event-et, amit már felül tusz írni:

clas Window1 ... { public event EventHandler StuffClicked; protected virtual void OnStuffClicked(EventArgs e) { EventHandler handler = StuffClicked; // thread safe if (handler != null) { hander(this, e); } } void stuff_Click(object sender, RoutedEventArgs e) { OnStuffClicked(new EventArgs()); } }

Innetől kezdve él a StuffClicked esemény, amihez azt a handlert teszed, amit csak akarsz.
Mutasd a teljes hozzászólást!

  • A kerdes megoldodott valahogy igy:

    <ItemsControl Name="NyelvValasztasItemsControl" ItemsSource="{Binding Source={StaticResource NyelvValasztas}}" Margin="20,20,20,20" > <ItemsControl.ItemContainerStyle> <Style TargetType="{x:Type ContentPresenter}"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Border Margin="10" CornerRadius="15" Name="BorderNEV" Background="LightGray" MouseLeftButtonUp="NyelvValasztasClick"> <StackPanel Name="NyelvValasztasa" Orientation="Horizontal"> <Image Name="Kep" Margin="20" Source="{Binding Converter={StaticResource NyelvImagePathConverter}}" Height="75"/> <TextBlock Margin="20" Foreground="White" Text="{Binding}" VerticalAlignment="Center" FontSize="20"/> </StackPanel> </Border> </DataTemplate> </Setter.Value> </Setter> </Style> </ItemsControl.ItemContainerStyle> </ItemsControl>

    Mostmar csak az a kerdes, hogy ha ezen osztaly peldanyat ismerem egy masik osztalyban, akkor miert nem latszik BorderNEV a NyelvValasztasItemsControl pedig igen? Szeretnem ezt hasznalni mashonnan, hogy az esemenykezelot mashonnan is megirhassam hozza...
    Mutasd a teljes hozzászólást!
  • A DataTemplate magyarul annyit tesz, hogy adatsablon. Egy ilyen sablon csak egy példányban létezik, és azt írja le, hogy az adott típusú elemet hogyan kell megjeleníteni, de nem kerül a sablon példányosításra azokon a helyeken, ahol felhasználod. Az eseménykezelőt a sablonban kell megírni, ha sablont használsz. Viszont a sablonban lévő elemeket el tudod érni a Children kollekción keresztül, ugyan úgy, mint ASP.NET alatt csak ott Controls volt a neve.
    Mutasd a teljes hozzászólást!
  • Viszont a sablonban lévő elemeket el tudod érni a Children kollekción keresztül...


    Hogyan?
    Mutasd a teljes hozzászólást!
  • A rossz hír az, hogy sehogy. Megnéztem, nem publikus az ItemsControl Children kollekciója. Meg is lehet érteni, hogy miért, hiszen ez egy tipikus data bound vezérlő.

    A jó hír: nem kell ez! Mer minek?? Az eseményvezérlőt a sablonban szokás megadni, és csak ott lehet, hiszen a sablon az egyetlen hely, ahol a tényleges WPF vezérlőkhöz hozzáférsz!!! A MSDN doksiban is ez van. Írok egy példát:

    XAML:

    <Window x:Class="ItemsControl.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ItemsControl" Height="300" Width="300" xmlns:s="clr-namespace:ItemsControl" > <Window.Resources> <s:Stuff x:Key="stuff" /> <DataTemplate DataType="{x:Type s:StuffItem}"> <StackPanel Orientation="Horizontal" Margin="2" MouseUp="stuff_Click"> <TextBlock Text="Name :" Margin="2" /> <TextBlock Text="{Binding Path=Name}" Margin="2" /> <TextBlock Text="Quantity :" Margin="2" /> <TextBlock Text="{Binding Path=Quantity}" Margin="2" /> </StackPanel> </DataTemplate> </Window.Resources> <StackPanel> <ItemsControl ItemsSource="{StaticResource stuff}" Name="stuffz" /> </StackPanel> </Window>

    Window.xaml.cs:

    public partial class Window1 : System.Windows.Window { public Window1() { InitializeComponent(); } void stuff_Click(object sender, RoutedEventArgs e) { StuffItem sitem = ((FrameworkElement)e.OriginalSource).DataContext as StuffItem; MessageBox.Show(string.Format("{0},{1}", sitem.Name, sitem.Quantity)); } }

    Stuff.cs:

    public class StuffItem { readonly Random rnd = new Random(); int _quantity; public int Quantity { get { return _quantity; } set { _quantity = value; } } string _name; public string Name { get { return _name; } set { _name = value; } } public StuffItem() { } public StuffItem(int idx) { _quantity = rnd.Next(2, 500); _name = string.Format("Stuff Item {0}" , idx); } } public class Stuff : ObservableCollection<StuffItem> { public Stuff() { for (int i = 0; i < 10; i++) { Add(new StuffItem(i)); } } }

    Ennyi. Nem kell ide trükközni, ha ilyen egyszerű! Nézd meg a példámban azt is, hogy mennyivel könnyebb megadni az adatsablont erőforrásként, mint a Te módszered. Igaz, hogy az is működik, de ha belegondolsz, akkor felesleges a stíluson keresztül lemenni a ContentPresenterig, hiszen csak arról van szó, hogy egy adott típusú objektumot meg kell jeleníteni valamilyen módon, és ennek az objektum típusához van köze, nem a vezérlők stílusához.
    Mutasd a teljes hozzászólást!
  • Sikerult kiszepitenem, de a fo problemam meg mindig megmaradt...
    A te peldadat alapul veve: a stuff_Click esemenyt nem tudom feluldefinialni egy masik osztalybol... Ezt kellene megoldani valahogy, ha lehet.
    Mutasd a teljes hozzászólást!
  • Nem. Például a template VisualTree tulajdonsága is null, ha XAML-ből állítja elő a rendszer, pedig ez lenne az a tulajdonság, ahol hozzáférhetnél ahhoz, hogy mi legyen a template tartalma. Nézd meg a Quick Watch-ben, ha nem hiszed el. Csak a nem publikus Optimized verzió érhető el, ha XAML-ből használod. Ugyan így nem tudsz belemenni az ItemsControl tartalmába sem. Ez rég nem WinForms, ahol csak úgy turkálni lehetet a vezérlők tartalmában. Ezt is megnézheted a Quick Watch-ben! Csupa olyan helyen van a tulajdonképpeni tartalom, ami nem publikus, és nem is eredeti, hanem valami optimalizált formában.

    De még mindig nem értem a problémád!!! Annyira túl akarod bonyolítani, hogy az nem igaz. Van már egy handlered a stuff_Click-hez, right? Akkor meg mi a gond? Át akarod definiálni? Tégy ki a Window-nak egy publikus event-et, amit már felül tusz írni:

    clas Window1 ... { public event EventHandler StuffClicked; protected virtual void OnStuffClicked(EventArgs e) { EventHandler handler = StuffClicked; // thread safe if (handler != null) { hander(this, e); } } void stuff_Click(object sender, RoutedEventArgs e) { OnStuffClicked(new EventArgs()); } }

    Innetől kezdve él a StuffClicked esemény, amihez azt a handlert teszed, amit csak akarsz.
    Mutasd a teljes hozzászólást!
  • Na ezt akakartam en, csak nemtudtam hogy is kell! Koszi
    Mutasd a teljes hozzászólást!
  • EventHandler -> EventHandler<EventArgs>

    Mutasd a teljes hozzászólást!
  • Most akkor jó, vagy nem? Elakadtál?
    Mutasd a teljes hozzászólást!
  • Ja... minden ok. Koszi, azthittem mar lezartam ezt a temat...
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd