Maybe this is a stupid asking, but I just wonder how to design this kind of layout:
first of all, I have a MenuList ObservableCollection. So I have to put these menus in to a stackPanel like this:
<Window.Resources>
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding ContentText}" Panel.ZIndex="{Binding PIndex}" Padding="10" FontSize="20"/>
</DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
so it looks like this:
after a while, there's a new bar under this menu added in:
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
.......
</ItemsControl>
<Border Background="Green" VerticalAlignment="Top" Panel.ZIndex="10" Height="30" Margin="0,81,0,0"/>
Now it's look like this:
The requirment is, if a button selected, it should on the top of the bar, other unselected buttons should be covered by the bar:
But the buttons' are in a StackPanel, so they're all based on StackPanel's ZIndex.
My question is, how to design such layout in xaml?
I think using the renderTransform is better. No need to hard code PIndex in xaml. See below.
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding}" Padding="10" FontSize="20" Height="30" Width="100">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.2"></ScaleTransform>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
<Border Background="Green" VerticalAlignment="Top" Height="30" Margin="0,150,0,0"/>
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Code behind:
public ObservableCollection<string> Menus { get; set; }
EDIT:
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{StaticResource image1}" Height="30" Width="100">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Border" Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}" Background="Orange">
</Border>
<ContentPresenter ContentSource="Content" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="RenderTransform" TargetName="Border">
<Setter.Value>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.2"></ScaleTransform>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
If the bar is literally just a green bar, you can also put it on the DataTemplate as a separate Stackpanel from the button, and then put a Style.Trigger on the Button's stackpanel to increase the ZIndex OnMouseOver. The bar would look seamless even if it is just repeating.
So instead of:
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding ContentText}" Panel.ZIndex="{Binding PIndex}" Padding="10" FontSize="20"/>
</DataTemplate>
You will have
<DataTemplate x:Key="MenuItemTemplate">
<Grid>
<StackPanel >
<StackPanel.Style>
<Style TargetType="StackPanel" >
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="3"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Panel.ZIndex" Value="1"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Width="100" Height="100" Content="{Binding ContentText}" Padding="10" FontSize="20" />
</StackPanel>
<StackPanel Panel.ZIndex="2">
<Border Background="Green" VerticalAlignment="Top" Height="30"/>
</StackPanel>
</Grid>
</DataTemplate>
(This doesn't look quite perfect if you run it, but you get the idea)
Dockpanel as our ItemPanelTemplate is the right choice.
Use a Grid with Button and Rectangle (for bottom border) as DataTemplate to show Menu items.
Don't apply margin in DataTemplate's Grid in step2 above. Instead use Grid Padding, Button margin for spacing.
DataTemplate :
<DataTemplate x:Key="MenuItemTemplate">
<Grid Background="DodgerBlue">
<Button Margin="5 5 5 0" HorizontalAlignment="Left" Panel.ZIndex="1" Content="{Binding ContentText}" Padding="1" Width="75" GotKeyboardFocus="Button_GotKeyboardFocus" LostKeyboardFocus="Button_LostKeyboardFocus"/>
<Rectangle Panel.ZIndex="2" Fill="BurlyWood" Height="5" Margin="0 25 0 0"/>
</Grid>
</DataTemplate>
ItemPanelTemplate :
<ItemsPanelTemplate>
<DockPanel Height="30" LastChildFill="True"/>
</ItemsPanelTemplate>
Use the below code as is :
<ItemsControl Panel.ZIndex="10" VerticalAlignment="Top" ItemsSource="{Binding Menus}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="0">
<ItemsControl.Resources>
<DataTemplate x:Key="MenuItemTemplate">
<Grid Background="DodgerBlue">
<Button Margin="0" HorizontalAlignment="Left" Panel.ZIndex="1" Content="{Binding ContentText}" Padding="1" Width="75" GotKeyboardFocus="Button_GotKeyboardFocus" LostKeyboardFocus="Button_LostKeyboardFocus"/>
<Rectangle Panel.ZIndex="2" Fill="BurlyWood" Height="5" Margin="0 25 0 0"/>
</Grid>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel Height="30" LastChildFill="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Code-Behind
public IList Menus { get; set; }
public Window1()
{
InitializeComponent();
Menus = new[] { new { ContentText = "Menu1" }, new { ContentText = "Menu2" }, new { ContentText = "Menu3" } };
this.DataContext = this;
}
private void Button_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Panel.SetZIndex((Button)e.OriginalSource, 12);
}
private void Button_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Panel.SetZIndex((Button)e.OriginalSource, 1);
}
Related
I have a grid that contains dynamically created buttons.
I have a selector tool that will select a "rectangle" of buttons and do whatever on them.
I'm stuck at this point, because I'm going down the MVVM route.. but I previously had a list of all the buttons and would do:
var buttonPos = button.TransformToAncestor(someGrid).Transform(new Point(0, 0));
Now I do not have the luxury of being able to get all the buttons in my itemscontrol to do that (or at least I don't know how).
This is a section of my XAML.
<Grid Name="mainGrid" DockPanel.Dock="Left" MouseDown="MainGrid_MouseDown" MouseUp="MainGrid_MouseUp" MouseMove="MainGrid_MouseMove" Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
MinWidth="{Binding GridWidth}" Height="{Binding GridHeight}">
<ItemsControl x:Name="ObjItemControl" ItemsSource="{Binding ObjCompositeCollection}">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Column}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid DockPanel.Dock="Top" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Name="objGrid" Grid.Row="1"
Width="{Binding MinWidth, ElementName=mainGrid}"
Height="{Binding Height, ElementName=mainGrid}"
engine:GridHelper.RowCount="{Binding RowCount}"
engine:GridHelper.ColumnCount="{Binding ColumnCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type engine:ObjA}">
<ToggleButton Content="{Binding Id}"
Tag="{Binding Id}"
IsChecked="{Binding IsSelected}"
Height="{Binding ElementName=ObjItemControl,
Path=DataContext.ButtonHeightWidth}"
Width="{Binding ElementName=ObjItemControl,
Path=DataContext.ButtonHeightWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{Binding ElementName=wellPlateItemControl,
Path=DataContext.ButtonMarginToUse}"
Padding="2"
PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown"
PreviewMouseLeftButtonUp="Button_PreviewMouseLeftButtonUp"
MouseEnter="Button_MouseEnter"
MouseLeave="Button_MouseLeave"
Style="{StaticResource ObjButton}">
</ToggleButton>
</DataTemplate>
<DataTemplate DataType="{x:Type engine:GridLabeller}">
<TextBlock Text="{Binding HeaderName}" Style="{StaticResource GridHeaders}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
<ItemsControl ItemsSource="{Binding RectForMarquee}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Width="{Binding Width}" Height="{Binding Height}"
Visibility="{Binding Visibility}"
Stroke="{StaticResource ResourceKey=SecondaryThemeColour}"
StrokeThickness="2" StrokeDashArray="2,1"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!--<Canvas>
<Rectangle x:Name="selectionBox" Visibility="Collapsed" Stroke="{StaticResource ResourceKey=SecondaryThemeColour}" StrokeThickness="2" StrokeDashArray="2,1"/>
</Canvas>-->
</Grid>
I want to be able to get all of the ObjA toggle buttons and do that TransformToAncestor check... unless there is a better way?
I can also do this in the View code-behind but not sure if this is a bit naughty...
private void MainGrid_MouseUp(object sender, MouseButtonEventArgs e)
{
// Need to find a better way for this...
List<UIElement> tgInItemControl = new List<UIElement>();
foreach (var toggleButton in VisualHelperExtensions.FindVisualChildren<ToggleButton>(ObjItemControl))
{
tgInItemControl.Add(toggleButton);
}
viewModel.MainGrid_MouseUp(tgInItemControl, e);
}
I need some advice. We noticed unusual behavior within the ScrollViewer. I have a StackPanel with whom I am more items including ListBox when the StackPanel placed in a ScrollViewer, when loading data to the listbox, a program for a brief moment freezes. When I am alone ListBox but everything works normally, no freezing of the program.
Here is my code:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="tStack" >
<Grid Height="300">
</Grid>
<Grid Height="300">
</Grid>
<ListBox x:Name="ListBox1" ItemsSource="{Binding AlbumsCvs.View, IsAsync=True}"
Style="{StaticResource ListBoxAlbumsTracksStyles}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingStackPanel.VirtualizationMode="Recycling" >
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource AlbumsHeader}" />
</ListBox.GroupStyle>
</ListBox>
</StackPanel>
</ScrollViewer>
<Style x:Key="ListBoxAlbumsTracksStyles" TargetType="{x:Type ListBox}">
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate >
<DockPanel>
<Border Background="#00000000"
Height="36"
Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}">
<DockPanel>
<TextBlock x:Name="TrackNumber"
DockPanel.Dock="Left" Margin="2,0,5,0"
Text="{Binding TrackNumber}"
VerticalAlignment="Center"
FontSize="13"
MinWidth="17"
Foreground="Black"/>
<DockPanel>
<TextBlock DockPanel.Dock="Left"
Text="{Binding TrackTitle}"
TextAlignment="Left"
FontSize="13"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
TextTrimming="CharacterEllipsis"
Margin="0,0,2,0"/>
<TextBlock DockPanel.Dock="Right"
Text="{Binding Duration}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
TextTrimming="CharacterEllipsis"
Margin="0,0,10,0"
FontSize="13" TextAlignment="Right"/>
</DockPanel>
</DockPanel>
</Border>
</DockPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- GroupItem -->
<Style x:Key="AlbumsHeader" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}" Background="#00000000">
<StackPanel Margin="0,0,0,15">
<StackPanel>
<TextBlock Text="{Binding AlbumName}"
DataContext="{Binding Items}"
Margin="0,5,0,0"
HorizontalAlignment="Stretch"
FontSize="20"
FontWeight="Light"
TextTrimming="CharacterEllipsis"
Foreground="Black"/>
<TextBlock Text="{Binding IdAlbum}"
DataContext="{Binding Items}"
Margin="0,0,0,10"
HorizontalAlignment="Stretch"
TextTrimming="CharacterEllipsis"
Foreground="Black"/>
</StackPanel>
<ItemsPresenter HorizontalAlignment="Stretch"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
code behind:
private async Task AlbumsArtistInformation()
{
if (string.IsNullOrEmpty(ArtistName))
return;
ObservableCollection<AlbumsArtistCollections> _albumsArtistCollections =
new ObservableCollection<AlbumsArtistCollections>();
try
{
var search = await spotifyDataService.GetArtists(ArtistName);
if (search == null) throw new ArgumentNullException(nameof(search));
foreach (var _artist in search.Artists.Items.Take(1))
{
this.IdArtist = _artist.Id;
}
var _artistAlbum = await spotifyDataService.GetArtistsAlbumsAsync(this.IdArtist, AlbumType.All);
if (_artistAlbum == null) throw new ArgumentNullException(nameof(_artistAlbum));
_albumsArtistCollections = _artistAlbum;
}
finally
{
// Unbind to improve UI performance
Application.Current.Dispatcher.Invoke(() =>
{
this.Albums = null;
this.AlbumsCvs = null;
});
Application.Current.Dispatcher.Invoke(() =>
{
this.Albums = _albumsArtistCollections;
});
Application.Current.Dispatcher.Invoke(() =>
{
// Populate CollectionViewSource
this.AlbumsCvs = new CollectionViewSource { Source = this.Albums };
//Group by Album if needed
this.AlbumsCvs.GroupDescriptions.Add(new PropertyGroupDescription("IdAlbum"));
});
}
}
Does anyone know how to solve this problem.
Vertically oriented StackPanel provides an unbounded available space for the the ListBox, when it calls MeasureOverride(Size availableSize) method, during layout. Therefore, the ListBox (which by default uses virtualization) should create the whole items and this is why you program freezes for a moment.
Therefore, use a DockPanel instead:
<DockPanel x:Name="tStack" LastChildFill="True" >
<Grid DockPanel.Dock="Top" Height="300">
</Grid>
<Grid DockPanel.Dock="Top" Height="300">
</Grid>
<ListBox DockPanel.Dock="Bottom" x:Name="ListBox1" ItemsSource="{Binding AlbumsCvs.View, IsAsync=True}"
Style="{StaticResource ListBoxAlbumsTracksStyles}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingStackPanel.VirtualizationMode="Recycling" >
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource AlbumsHeader}" />
</ListBox.GroupStyle>
</ListBox>
</DockPanel>
LastChildFill is true by default. The ListBox should be the last element, in order to fill the space.
As another option, you can set the Height of the ListBox and put the DockPanel in a ScrollViewer or you can consider a Grid with splitters as another option.
I have searched around for this, found some solutions related to Winforms, and some even just saying it is really difficult in WPF to accomplish, but those posts are quite old.
If I have a standard ListBox, which is declared as:
<ListBox
x:Name="listBox"
HorizontalAlignment="Left"
Height="240"
Margin="401,68,0,0"
VerticalAlignment="Top"
Width="345"
SelectionChanged="listBox_SelectionChanged"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Grid.ColumnSpan="2"/>`
and programmatically:
System.ComponentModel.BindingList<string> listItems = new System.ComponentModel.BindingList<string>();
listBox.ItemsSource = listItems;
Is there a way for these strings to be wrapped within the ListBox?
Not hard at all:
<ListBox
....
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock
Text="{Binding}"
TextWrapping="Wrap"
/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you got StackPanel please get rid of them. They are bad with wrapping. Use GRID instead like #EdPlunkett suggested.
To use this:
<ItemsControl ItemsSource="{Binding MyErrors, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Template="{StaticResource ErrorListContainerTemplate}"
ItemContainerStyle="{StaticResource ErrorListStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
/>
Here is my style code:
<Style TargetType="{x:Type TextBlock}" x:Key="WrappingStyle">
<Setter Property="TextWrapping" Value="WrapWithOverflow"/>
</Style>
<Style TargetType="ContentPresenter" x:Key="ErrorListStyle">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TextBoxBorderErrorColor}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border Margin="0,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Grid.Column="0" Fill="{DynamicResource TextBoxBorderErrorColor}" VerticalAlignment="Top" HorizontalAlignment="Left">
<Path.Data>
<EllipseGeometry RadiusX="2.5" RadiusY="2.5"/>
</Path.Data>
</Path>
<ContentPresenter Grid.Column="1" Content="{Binding}" VerticalAlignment="Top">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource WrappingStyle}"/>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I have a ListView inside a ListView and when the mouse is over the inner ListView, the outer ListView stops scrolling.
The scroll works when the mouse is over the items in the outer ListView and when the mouse is over the scroll bar.
XAML:
<Window x:Class="ListViewInsideListViewNoteScrolling.CheckForUpdatesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CheckForUpdatesView" Height="300" Width="500">
<Grid>
<ListView Grid.Row="0" Margin="20 10" BorderThickness="0" BorderBrush="Transparent"
HorizontalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="False"
ItemsSource="{Binding VersionsDetails}"
ItemContainerStyle="{StaticResource CheckForUpdatesListView}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="400">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontWeight="Bold">
<Run Text="Version "/> <Run Text="{Binding Number}"/>
</TextBlock>
<TextBlock Grid.Row="1" Text="{Binding Description}" TextWrapping="Wrap"/>
<ListView Grid.Row="2" Margin="10 0 0 0" BorderThickness="0" BorderBrush="Transparent"
ItemsSource="{Binding Details}"
ItemContainerStyle="{StaticResource CheckForUpdatesListView}">
<ListView.ItemTemplate>
<DataTemplate>
<BulletDecorator Margin="4">
<BulletDecorator.Bullet>
<Ellipse Height="5" Width="5" Fill="Black"/>
</BulletDecorator.Bullet>
<TextBlock TextWrapping="Wrap" Text="{Binding}" Width="350"></TextBlock>
</BulletDecorator>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!--<TextBlock Grid.Row="3" Text="{Binding Details, Converter={StaticResource ListToTextConverter}}" TextWrapping="Wrap"/>-->
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
Style:
<Style x:Key="CheckForUpdatesListView" TargetType="ListViewItem">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Padding="0" BorderThickness="0" SnapsToDevicePixels="true" Background="Transparent">
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
VersionsDetails is a List<VersionInfo>
public class VersionInfo
{
public string Number { get; set; }
public string Description { get; set; }
public List<string> Details { get; set; }
}
One possible solution is, instead of the inner ListView, to use this line
<TextBlock Grid.Row="3" Text="{Binding Details, Converter={StaticResource ListToTextConverter}}" TextWrapping="Wrap"/>
which will convert my list into a bulleted string, but the styling is better with the ListView.
I am also open to suggestions for using other Wpf controls/elements to solve this issue.
A nice solution would be to create a behavior to ignore mouse wheel.
1> Import System.Windows.Interactivity
2> Create the behavior:
public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewMouseWheel += AssociatedObjectPreviewMouseWheel;
}
protected override void OnDetaching()
{
AssociatedObject.PreviewMouseWheel -= AssociatedObjectPreviewMouseWheel;
base.OnDetaching();
}
private void AssociatedObjectPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var mouseWheelEventArgs = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = UIElement.MouseWheelEvent
};
AssociatedObject.RaiseEvent(mouseWheelEventArgs);
}
3> Attached the behavior to your inside ListView
<ListView Grid.Row="2" Margin="10 0 0 0" BorderThickness="0"
ItemsSource="{Binding Details}"
ItemContainerStyle="{StaticResource CheckForUpdatesListView}">
<i:Interaction.Behaviors>
<local:IgnoreMouseWheelBehavior />
</i:Interaction.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<BulletDecorator Margin="4">
<BulletDecorator.Bullet>
<Ellipse Height="5" Width="5" Fill="Black"/>
</BulletDecorator.Bullet>
<TextBlock TextWrapping="Wrap" Text="{Binding}" Width="350"></TextBlock>
</BulletDecorator>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Inspired by this close question : Bubbling scroll events from a ListView to its parent
I have a dynamically generated DataGrid bound to a DataTable property in my ViewModel.
I have AutoGenerateColumnHeaders = true, and it's working fine. However, I'm using a DataTemplate to cover the Header with a StackPanel containing a Label and Button. I cannot seem to figure out how to bind the Label Content to the DataGridColumnHeader. I have tried with and without FindAncestor, but I believe the following is the closest to where I need to be...Question is on the Label Content="{}"
<local:UserControlViewBase.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Width="Auto" Orientation="Horizontal">
<Label Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:UserControlViewBase}},Path=DataContext.TestList.ColumnName}" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:UserControlViewBase.Resources>
//local:UserControlViewBase is just a UserControl with some extra bells and whistles added.
I'm fairly new to WPF and I'm assuming I'm just missing something with the binding - I'm still learning.
Thanks.
This is what I did to get it to work. I had to change the findancestor to look for the DataGridColumnHeader instead of the user control. I then was able to access the Column.Header property:
<local:UserControlViewBase.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Width="Auto" Orientation="Horizontal">
<Label Width="75" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridColumnHeader}},Path=Column.Header}" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:UserControlViewBase.Resources>