WPF: Get control from ListView DataTemplate in Code Behind - c#

I've created a ListView with a selfmade ItemTemplate, that is quite nested:
<ListView x:Name="QuestionListView" ItemsSource="{Binding QuestionList, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Background="#afafaf" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" CornerRadius="15,0,0,15" BorderBrush="Gray" BorderThickness="0,0,1,0" Background="#676767" />
<Border Grid.Column="1" BorderBrush="Gray" BorderThickness="0,3,1,3" Background="#8f8f8f" />
<Border Grid.Column="2" CornerRadius="0,15,15,0" BorderThickness="1" BorderBrush="Gray" Background="#676767" />
<Label Content="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" Foreground="Beige" />
<!--This is the TextEditor, I need in my Code behind-->
<Viewbox Grid.Column="1">
<avalonEdit:TextEditor xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" Name="textEditor" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Stretch" Width="600" FontSize="30" Background="Transparent" BorderBrush="Transparent" Foreground="Beige" PreviewLostKeyboardFocus="RichTextBox_PreviewLostKeyboardFocus" FontFamily="Consolas">
<i:Interaction.Behaviors>
<beh:AvalonEditBehaviour GiveMeTheText="{Binding TextQuestion, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</i:Interaction.Behaviors>
</avalonEdit:TextEditor>
</Viewbox>
<!--<TextBlock Grid.Column="1" IsHitTestVisible="False" FontSize="25" FontWeight="Bold" Foreground="LightGray" Text="Your question here" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding TextQuestion, Mode=TwoWay}" Value="">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>-->
<StackPanel Orientation="Horizontal" Grid.Column="2" HorizontalAlignment="Center">
<Button Margin="10,0,5,0" Width="40" Height="40" Background="Gray" Command="{Binding EditCommand}" MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave">
<Image Source="{Binding EditImage}" />
</Button>
<Button Margin="5,0,10,0" Width="40" Height="40" Background="Gray" Command="{Binding DeleteCommand}">
<Image Source="{Binding DeleteImage}" />
</Button>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
Now I want to get the TextEditor textEditor in my code behind, because I need it for the "Intellisense" window, I am customizing.
So I have this in my Code behind:
public partial class QuestionListUC : UserControl
{
TextEditor editor;
public QuestionListUC()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
var template = QuestionListView.Template;
editor = (TextEditor)template.FindName("textEditor", QuestionListView);
}
}
But the FindName-Method outputs nothing for me, the variable "editor" is null.
What am I doing wrong here?

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() => {
var template = QuestionListView.ItemTemplate;
editor = (TextEditor)template.FindName("textEditor",
QuestionListView);
}), DispatcherPriority.DataBind);
}
This should work
The most important change is
var template = QuestionListView.ItemTemplate;
The Dispatcher just delays the action until the data binding has been done, so the ItemTemplate should not be null

I managed to get a ViewBox around the Editor and then just use it's child. now I have the control in my CB

Related

UWP: Problem when trying to change the background color of a ListView item

I have a uwp desktop application with a listview in which I need to change the background color of items whose given value is empty. I've already done everything indicated by the answer to the question below, but the color doesn't change. Any help is most welcome.
uwp: how to change background color of listview item based on its value?
https://zamjad.wordpress.com/2010/01/01/applying-style-conditionally/
XAML
<Page.Resources>
<Style x:Key="SpeechLineTimingSet" TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style x:Key="SpeechLineTimingNotSet" TargetType="ListViewItem">
<Setter Property="Background" Value="Red" />
</Style>
<local:SpeechLineListViewStyleSelector x:Key="SpeechLineListViewStyleSelectorObject"
SpeechLineTimingSetStyle="{StaticResource SpeechLineTimingSet}"
SpeechLineTimingNotSetStyle="{StaticResource SpeechLineTimingNotSet}"/>
</Page.Resources>
<ListView x:Name="dtgSpeechLines" Grid.Column="0" Grid.Row="2" Margin="3,0,3,3"
BorderBrush="Gray" BorderThickness="1" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ItemContainerStyleSelector="{StaticResource SpeechLineListViewStyleSelectorObject}"
DoubleTapped="dtgSpeechLines_DoubleTapped">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.HeaderTemplate>
<DataTemplate>
<Grid Padding="12" Margin="3,5,3,5" Background="{ThemeResource SystemBaseLowColor}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Uid="CtrPgLvwColumn0" Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock Grid.Column="1" x:Uid="CtrPgLvwColumn1" Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock Grid.Column="2" x:Uid="CtrPgLvwColumn2" Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock Grid.Column="3" x:Uid="CtrPgLvwColumn3" Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock Grid.Column="4" x:Uid="CtrPgLvwColumn4" Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock Grid.Column="5" x:Uid="CtrPgLvwColumn5" Style="{ThemeResource CaptionTextBlockStyle}"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="3,5,3,5" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextWrapping="Wrap" FontSize="12" Text="{Binding Number}" />
<TextBlock Grid.Column="1" TextWrapping="Wrap" FontSize="12" Text="{Binding OriginalText}"/>
<TextBlock Grid.Column="2" TextWrapping="Wrap" FontSize="12" Text="{Binding TextForAudio}"/>
<TextBlock Grid.Column="3" TextWrapping="Wrap" FontSize="12" Text="{Binding SubtitleNumber}"/>
<TextBlock Grid.Column="4" TextWrapping="Wrap" FontSize="12" Text="{Binding Start}"/>
<TextBlock Grid.Column="5" TextWrapping="Wrap" FontSize="12" Text="{Binding Length}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
CODE BEHIND
public class SpeechLineListViewStyleSelector : StyleSelector
{
public Style SpeechLineTimingSetStyle { get; set; }
public Style SpeechLineTimingNotSetStyle { get; set; }
protected override Style SelectStyleCore(object item, DependencyObject container)
{
SpeechLine speechLine = item as SpeechLine;
if (speechLine != null)
{
if (speechLine.Start == "")
{
return SpeechLineTimingNotSetStyle;
}
else
{
return SpeechLineTimingSetStyle;
}
}
return base.SelectStyleCore(item, container);
}
}
Please remove the ListView.ItemContainerStyle that you defined in the ListView. It overrides the style that you defined in the StyleSelector. Just put the HorizontalContentAlignment setting in the styles in the SpeechLineListViewStyleSelector.
Like:
<Style x:Key="SpeechLineTimingSet" TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style x:Key="SpeechLineTimingNotSet" TargetType="ListViewItem">
<Setter Property="Background" Value="Red" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
And:

Change Text of Textblock in controltemplate

I have a list of items which a user can select and I would like to add an explanation text. So far I have this code
<TabItem Name="TabItem02" Header="">
<ListBox Name="listBox01" VerticalAlignment="Stretch" SelectionMode="Multiple" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedValuePath="Content">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<CheckBox Margin="5,2" IsChecked="{TemplateBinding IsSelected}" Grid.Column="0" VerticalAlignment="Top">
<ContentPresenter VerticalAlignment="Center">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="{TemplateBinding Content}" TextWrapping="Wrap" />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</CheckBox>
<Expander Header="Explanation" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Right" FlowDirection="RightToLeft">
<TextBlock TextWrapping="Wrap" FlowDirection="LeftToRight"/>
</Expander>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBoxItem Name="List1Item01" IsEnabled="False"/>
<ListBoxItem Name="List1Item02" IsEnabled="False"/>
<ListBoxItem Name="List1Item03" IsEnabled="False"/>
<ListBoxItem Name="List1Item04" IsEnabled="False"/>
<ListBoxItem Name="List1Item05" IsEnabled="False"/>
</ListBox>
</TabItem>
And at the moment I am changing the content of each ListBox through a ressourcefile with this code-behind
foreach (ListBox listBox in ListBoxes)
{
foreach (ListBoxItem item in listBox.Items) item.Content = resourceManager.GetString(item.Name);
}
I would like to change the text of the second TextBlock (the one in the Expander) according to the ListBoxItem it belongs to as easy as the ListBox content itself through the ressourcefile. I would prefer not to create a separate Expander + TextBlock for each ListBoxItem with a separate name.
So if anyone has a solution for my problem, I would really appreciate that.

listbox inside ScrollViewer - freeze program

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.

WPF ListView inside ListView not scrolling when mouse over the inner ListView

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

How to use wpf expender alignment

I am trying to create a WPF window to have a simple expander to extend the datagrid when the user clicks on the More expander button. When the user wants to hide the datagrid, user just has to clik on the Less expander button.
I am also using dock panel to separate header, left, right and footer.
The problems are :
I want to have the less button to be in center before the user
click on the more expander button. When the user clicks on the more
expander button, the less button will be pushed to the left, to show
the datagrid on the right.
How do I change the name of the expander when its closed and
open. Can I do it at the xaml level?
Below is the xaml code:
<Window x:Class="M.SalesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SalesWindow" Height="300" Width="300">
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<Label FontSize="28" Content="Sales">
</Label>
</StackPanel>
<StackPanel DockPanel.Dock="Left" Width="auto" HorizontalAlignment="Center">
<Label FontSize="15" Content="Enter Amount" Height="26" Width="168" />
<Separator Width="168" />
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Expander ExpandDirection="Left" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Expander.Header>
<TextBlock Text="More">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<Expander.Content>
<StackPanel>
<DataGrid ItemsSource="{Binding Products}">
</DataGrid>
</StackPanel>
</Expander.Content>
</Expander>
</StackPanel>
</DockPanel>
</Window>
Thank you.
Replace your code with the below code and see the magic. This will also solve your problem of alignment as per your requirement. I have removed the DockPanel as you can achieve the similar result with this piece of code.
<StackPanel>
<StackPanel>
<Label FontSize="28" Content="Sales">
</Label>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" HorizontalAlignment="Center">
<Label FontSize="15" Content="Enter Amount" Height="26" Width="168" />
<Separator Width="168" />
</StackPanel>
<Expander Grid.Column="1" ExpandDirection="Left" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="IsExpanded" Value="False" />
<Setter Property="Header">
<Setter.Value>
<TextBlock Text="Less">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsExpanded,RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Header">
<Setter.Value>
<TextBlock Text="More">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Content>
<StackPanel>
<DataGrid ItemsSource="{Binding Products}">
</DataGrid>
</StackPanel>
</Expander.Content>
</Expander>
</Grid>
</StackPanel>
The trick lies under the following lines of code.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

Categories

Resources