WPF – Übergeodnetes ListView DataItem erhalten

by robert 12. June 2009 02:30

In einem ItemPanelItem eines ListViews wird bei Mausklick ein Event gefeuert: Wie erhalten wir das DataItem für diesen ListView? //Click event des Bildes private void btnShowDetails_Click(object sender, RoutedEventArgs e) { //auf der Suche nach dem zu Grunde liegenden DataItem var displayItem = lvLogItems.GetDataItemItem<LogDisplayItem>(e);   //hier folgt die eigentlich Arbeit } “GetDataItem” ist eine ExtensionMethod die im visuellen Baum solange von Eltern-Element zu Eltern-Element wandert, bis das übergeordnete ListViewItem erreicht ist. Mit dem ListViewItem ist auch das DataItem zu erreichen. Die Extension Method wird in folgender Klasse definiert und ist auch den nächsten Tagen in Speak-Lib zu finden. public static class ListViewUtils { public static TDataItem GetDataItemItem<TDataItem>(this ListView listView, RoutedEventArgs e) { var dependencyObject = (DependencyObject)e.OriginalSource;   return GetDataItem<TDataItem>(dependencyObject, listView); }   public static TDataItem GetDataItemItem<TDataItem>(this ListView listView, DependencyObject dependencyObject) { return GetDataItem<TDataItem>(dependencyObject, listView); }   private static TDataItem GetDataItem<TDataItem>(DependencyObject dependencyObject, ListView listView) { while ((dependencyObject != null) && !(dependencyObject is ListViewItem)) dependencyObject = VisualTreeHelper.GetParent(dependencyObject);   return (TDataItem)listView.ItemContainerGenerator.ItemFromContainer(dependencyObject); } } Ich hoffe es nützt:-)

enjoyed the post?

Tags:

WPF

WPF – Fenster öffnet sich im Hintergrund?

by robert 12. June 2009 00:59

Öffnet man ein WPF-Window über Quelltext aus einem UserControl heraus, dann landet das neue Fenster hinter dem zu öffnenden Fenster. Die Problemlösung ist das Zuweisen des Window Owners. var logItemDetail = new frmLogItemDetail(logDisplayItem); logItemDetail.Owner = this.FindLogicalAncestorByType<Window>(); logItemDetail.Show() “FindLogicalAncestor” ist ein Extension Method für DependencyObjects und stammt aus dem WPF-Contrib Projekt und ist nun auch aus Bequemlichkeitsgründen in Speak-Lib zu finden.

enjoyed the post?

Tags:

WPF

WPF ListView Performance – Booooost für Templates

by robert 9. June 2009 18:08

Folgendes Video zeigt eine WPF ListView mit 2Millionen einträgen:   Out Of the Box ist der WPF ListView rasant schnell. Verwendet man jedoch ein Semi-kompliziertes DataTemplate, bricht die Performance ein. Der Problem-Listview im Gegensatz zum Beispielvideo benötigt der folgende ListView schon bei 1490 Elementen eine Renderzeit von fast 10 Sekunden. Hier die Definition des ListViews: <ListView Grid.Row="1" x:Name="lvLogItems" ItemsSource="{Binding Source={StaticResource myList}}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" Style="{StaticResource lbResultStyle}" ItemContainerStyle="{StaticResource lbResultItemStyle}" ItemTemplate="{StaticResource itemTemplate}"> </ListView>   Die Definition des ItemTemplates: <DataTemplate x:Key="itemTemplate"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="1" /> </Grid.RowDefinitions> <DockPanel Grid.Row="0"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="30" /> <ColumnDefinition /> <ColumnDefinition Width="130"/> <ColumnDefinition Width="22"/> </Grid.ColumnDefinitions> <DockPanel Grid.Column="0" Margin="0,1,0,0" > <!--Background="AliceBlue"--> <Image Name="imgStatus" Height="20" VerticalAlignment="Top"/> </DockPanel>   <DockPanel Grid.Column="1" Margin="3,1,0,0"><!--Background="BurlyWood"--> <TextBlock Text="{Binding Path=StatusText}" TextWrapping="Wrap"></TextBlock> </DockPanel> <Grid Grid.Column="2"> <Grid.RowDefinitions> <RowDefinition Height="16" /> <RowDefinition Height="6" /> <RowDefinition Height="12" /> <RowDefinition Height="12" /> </Grid.RowDefinitions> <DockPanel> <TextBlock Grid.Row="0" Text="Dauer: " FontSize="16" FontWeight="ExtraLight" /> <TextBlock Grid.Row="1" Text="{Binding Path=Duration}" FontSize="16" FontWeight="bold"></TextBlock> </DockPanel> <DockPanel Grid.Row="2"> <TextBlock Grid.Row="0" Text="Von: " FontSize="11" Width="28" /> <TextBlock Text="{Binding Path=StartTime, StringFormat=\{0:MM:dd.yy HH:mm:ss\}}" FontSize="11"></TextBlock> </DockPanel> <DockPanel Grid.Row="3"> <TextBlock Grid.Row="0" Text="Bis: " FontSize="11" Width="28" /> <TextBlock Text="{Binding Path=EndTime, StringFormat=\{0:MM:dd.yy HH:mm:ss\}}" FontSize="11"></TextBlock> </DockPanel> </Grid> <Image Grid.Column="3" Source="..\Resources\application_view_detail.png" Margin="0,2,3,0" Height="16" VerticalAlignment="Top"></Image>   <Image Grid.Column="3" Source="..\Resources\email.png" Margin="0,20,3,0" Height="16" VerticalAlignment="Top"></Image>   </Grid>   Hier die Defintion des ItemContainerStyles: <Style x:Key="lbResultStyle" TargetType="ListView"> <Setter Property="Margin" Value="0"/> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate > <StackPanel IsItemsHost="True" Orientation="Vertical" Width="{Binding ElementName=lvResult,Path=ActualWidth}" > </StackPanel> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style>   VirtualizingStackPanel zur Hilfe Die Reduzierung der zähen Ladezeit erfolgt über eine triviale Änderung: Statt der Verwendung des StackPanel als ItemHost wird ein “VirtualizingStackPanel“ verwendet: <Style x:Key="lbResultStyle" TargetType="ListView"> <Setter Property="Margin" Value="0"/> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate > <VirtualizingStackPanel IsItemsHost="True" Orientation="Vertical" Width="{Binding ElementName=lvResult,Path=ActualWidth}" > </VirtualizingStackPanel> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> Der Effekt ist eine dramatische Verkürzung der 10-sekündígen Renderzeit hinzu einer sofortige Darstellung des Grids. Wie funktioniert es? Das Zauberwort in WPF heißt Virtualisierung: Der gewaltige Performance Unterschied wird erreicht, durch die Art und Weise wie das VirtualizingStackPanel die Scrollhöhe bestimmt. Statt die Höhe eines jeden Elements auszurechnen (und dafür zu rendern), wird nur der Index des Elements für die Bestimmung der ScrollPosition verwendet. Wird nun gescrollt müssen nur die Elemente gerendert werden, die tatsächlich sichtbar sind. Lesenswert: WPF Data Virtualization (auf Codeplex: Verzögertes laden der zu zeigenden Daten) Beispielprojekt für eine Virtualisiertes Panel IScrollInfo part I IScrollInfo part II IScrollInfo part III IScrollInfo part IV

enjoyed the post?

Tags:

WPF

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for javascript. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our children. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.