I would bind an ICommand on left double click event on item in the ListView.
I tried the solution below but doesn't work properly, the Execute function is called when I click the ListView not the item in the list. Someone has any suggestion ?
<ListView x:Name="history_list_view" HorizontalAlignment="Left" Height="210" Margin="25,194,0,0"
VerticalAlignment="Top" Width="656" Background="#FF2F2B2B" Foreground="White"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}">
<ListView.InputBindings >
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding SelectedItemCommand}" CommandParameter="{Binding SelectedItem}"/>
</ListView.InputBindings>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#7f8c8d"/>
<Setter Property="BorderThickness" Value="0" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#7f8c8d"/>
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView >
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Header="Lot" Width="170" DisplayMemberBinding="{Binding Lot}"/>
<GridViewColumn Header="Code" Width="160" DisplayMemberBinding="{Binding Code}"/>
<GridViewColumn Header="Rev" Width="80" DisplayMemberBinding="{Binding Rev}"/>
<GridViewColumn Header="User" Width="140" DisplayMemberBinding="{Binding User}"/>
<GridViewColumn Header="Date" Width="100" DisplayMemberBinding="{Binding Date}"/>
</GridView>
</ListView.View>
</ListView>
Either add an EventSetter for the MouseDoubleClick event in the ItemContainerStyle and invoke the command from the event handler in the code-behind, or use an attached behaviour to execute the command:
public static class DoubleClickBehavior
{
public static ICommand GetCommand(ListViewItem obj) => (ICommand)obj.GetValue(CommandProperty);
public static void SetCommand(ListViewItem obj, ICommand value) => obj.SetValue(CommandProperty, value);
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(DoubleClickBehavior), new PropertyMetadata(null, OnCommandChanged));
private static void OnCommandChanged(object sender, DependencyPropertyChangedEventArgs e)
{
ListViewItem lvi = (ListViewItem)sender;
lvi.MouseDoubleClick += Lvi_MouseDoubleClick;
}
private static void Lvi_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListViewItem lvi = (ListViewItem)sender;
ICommand command = GetCommand(lvi);
if (command != null)
command.Execute(null);
}
}
XAML:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="local:DoubleClickBehavior.Command"
Value="{Binding DataContext.SelectedItemCommand, RelativeSource={RelativeSource AncestorType=ListView}}" />
</Style>
</ListView.ItemContainerStyle>
Another simple solution is to override the ControlTemplate of the ListBoxItem to set the InputBindings on it:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.InputBindings>
<MouseBinding MouseAction="{x:Static MouseAction.LeftDoubleClick}"
Command="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=DataContext.SelectPageCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=SelectedItem}" />
</Border.InputBindings>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Alternatively turn the complete item into a Button:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Button Content="{TemplateBinding Content}"
Command="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=DataContext.SelectedItemCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=SelectedItem}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
You surely want to style the items to remove the button look.
Related
I have a ListView where some columns contains TextBox controls for the user to enter text. However, if the entered text is too long it will be limited by the current width of the column. Is there a way to automatically resize the width of the column when text is entered overflowing the current size of the column?
<ListView x:Name="List1"
Grid.Column="1"
Margin="0 0 5 20"
Background="Transparent"
Foreground="White"
BorderThickness="0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ItemsSource="{Binding Path=Stations}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListViewItem}}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView AllowsColumnReorder="False">
<!-- Location -->
<GridViewColumn Header="Location">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Text" Value="{Binding Location, Mode=TwoWay}"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
You could try to handle the TextChanged event and measure the desired size of the TextBox:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
if (textBox.DesiredSize.Width > col.Width)
col.Width = textBox.DesiredSize.Width;
}
XAML:
<GridViewColumn Width="100" x:Name="col">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox TextChanged="TextBox_TextChanged">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Text" Value="{Binding Location, Mode=TwoWay}"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I've created a "DarkMode" theme for my application but the IsSelected binding for the ListViewItem is not working. When I select an item/items they highlight as expected (I.e. the MultiTriggers are applying the correct highlight colour), so the ListView obviously thinks IsSelected == True. But the Setter is never called so the property in my model is never updated.
If I remove the x:Key="RemoteComputerItem" style it works fine (I.e. the Setter is called and my model is updated). Removing all of the triggers in that style make no difference (I obviously don't see the items being highlighted, but the Setter is still not called). So that only leaves the following:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
</Border>
</ControlTemplate>
I believe the problem lies within the control template above, but I can't figure out how to fix it. Am I missing something? or do I need to use something else in place of the GridViewRowPresenter?
My XAML is below. I haven't included the C# as I think the problem lies here and don't want to make the question too long, but I'm happy to add it if needed.
View:
<ListView x:Name="ADComputers" Margin="0" Padding="0" Grid.Row="1" Grid.Column="2"
ItemsSource="{Binding SelectedItem.Computers, ElementName=ADTree, Mode=TwoWay}"
SelectionMode="Multiple" ItemContainerStyle="{DynamicResource RemoteComputerItem}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource RemoteComputerItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Style.Triggers>
<DataTrigger Binding="{Binding StatusText}" Value="Offline">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="" Width="20">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="Name" Width="120" DisplayMemberBinding="{Binding Name}">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Computer Name" util:SortOrderGlyph.IsSorted="False" util:SortOrderGlyph.SortDirection="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SortCol">
<cal:Parameter Value="Name" />
<cal:Parameter Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewColumnHeader}}}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<!-- More columns like above, removed to shorten -->
</GridView>
</ListView.View>
</ListView>
Separate Resource Dictionary for DarkMode theme:
<Style x:Key="RemoteComputerItem" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource ControlMouseOverColor}" />
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource SelectedBackgroundColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource SelectedBackgroundColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT:
Here is some more code to give you the full picture of the bindings, but as I mentioned above the bindings work perfectly when I remove the control template for the ListViewItem.
As you can see above, the ListView is bound to SelectedItem.Computers of the element ADTree. Here is the XAML for ADTree:
<TreeView Margin="0, -1, 0, 0" Grid.Row="1" Grid.Column="0" x:Name="ADTree" ItemsSource="{Binding ADRoot.Children}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:OUModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
The TreeView is bound to ADRoot.Children:
class ADTreeViewModel : OUModel
{
public OUModel ADRoot { get; set; } = new OUModel(null, false);
}
class OUModel : PropertyChangedBase, ITreeViewItemViewModel
{
// TreeView is bound to this property, which holds a collection of more OUModel objects
public BindableCollection<ITreeViewItemViewModel> Children { get; set; } = new BindableCollection<ITreeViewItemViewModel>();
// The ListView's ItemSource is bound to ADTree.SelectedItem.Computers which is this property
public List<RemoteComputer> Computers
{
get { return computers; }
set { computers = value; NotifyOfPropertyChange(); }
}
// PropertyChangedBase is from Caliburn.Micro
class RemoteComputer : PropertyChangedBase
{
// All other properties in this class are being displayed correctly in the ListView, so the DataContext is correct E.g.:
public string Name { get; set; }
private bool isSelected = false;
// The ListViewItem's IsSelected property is bound to this
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
NotifyOfPropertyChange(); // Caliburn.Micro gets the property name itself
// I've also tried adding the following
NotifyOfPropertyChange(() => Parent.Children);
NotifyOfPropertyChange(() => Parent);
}
}
}
Here is the Live Property Explorer for an item which IS selected:
I'm using MVVM in a WPF application. I've a UserControl whose DataContext is set to a ViewModel. The UserControl is a table with 3 columns.
This is the following ListView/GridView:
<DockPanel>
<ListView DockPanel.Dock="Top" ItemsSource="{Binding Items}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ctrl:ListViewLayoutManager.Enabled="True">
<ListView.View>
<GridView>
<GridViewColumn Header="{Binding ColumnHeader1}"
CellTemplate="{StaticResource cellTemplateColumn1}">
<GridViewColumn.HeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="GridViewColumnHeader">
<Setter Property="TextBlock.TextAlignment" Value="{Binding Column1HAlignment}" />
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
<GridViewColumn Header="{Binding ColumnHeader2}"
CellTemplate="{StaticResource cellTemplateColumn2}">
<GridViewColumn.HeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="GridViewColumnHeader">
<Setter Property="TextBlock.TextAlignment" Value="{Binding Column2HAlignment}" />
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
<GridViewColumn Header="{Binding ColumnHeader3}"
CellTemplate="{StaticResource cellTemplateColumn3}"
ctrl:RangeColumn.IsFillColumn="True">
<GridViewColumn.HeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="GridViewColumnHeader">
<Setter Property="TextBlock.TextAlignment" Value="{Binding Column3HAlignment}" />
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</DockPanel>
This is achieved by the following resources:
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<TextBlock Text="{TemplateBinding Content}" Margin="5" Width="{TemplateBinding Width}">
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
<DataTemplate x:Key="cellTemplateColumn1">
<fa:ImageAwesome Icon="{Binding IconType}" Foreground="{Binding Status}" Width="10" />
</DataTemplate>
<DataTemplate x:Key="cellTemplateColumn2">
<TextBlock Text="{Binding SerialNumber, StringFormat='0'}" />
</DataTemplate>
<DataTemplate x:Key="cellTemplateColumn3">
<TextBlock Text="{Binding Action}" TextWrapping="Wrap" />
</DataTemplate>
The text alignments of each column is settable through the view model. I can do this easily for the headers:
<GridViewColumn.HeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="GridViewColumnHeader">
<Setter Property="TextBlock.TextAlignment" Value="{Binding Column1HAlignment}" />
</Style>
</GridViewColumn.HeaderContainerStyle>
But how can I pass the same parameter (Column1HAlignment) to align the cell's TextBlock contents?
Note the alignment of the 2nd column (where header is #) in the image above. The header is right aligned through data binding. I want the same binding for each cell content.
You could bind the HorizontalAlignment property of the element in the CellTemplate to the Column1HAlignment source property using a {RelativeSource}:
<DataTemplate x:Key="cellTemplateColumn2">
<TextBlock Text="{Binding SerialNumber, StringFormat='0'}"
HorizontalAlignment="{Binding DataContext.Column1HAlignment,
RelativeSource={RelativeSource AncestorType=ListView}}"/>
</DataTemplate>
I have a listview that uses GroupStyles where the ColumnHeaders are shown in each group. This works fine.
I would however like to hide the original ListView ColumnHeader (seen at the top of image) and just show Headers within the groups.
How can I separate them so it only show in the groups?
The GroupStyle:
<Style x:Key="GroupingSerialStyle" TargetType="{x:Type GroupItem}" BasedOn="{StaticResource GroupingBase}">
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate>
<Expander Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsExpanded="{Binding IsExpandedAll, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Mode=OneTime}" Margin="2">
<Expander.Header>
<StackPanel Orientation = "Horizontal">
<TextBlock Text=" # "/>
<TextBlock Text = "{Binding Name}" />
</StackPanel>
</Expander.Header>
<StackPanel Orientation="Vertical">
<GridViewHeaderRowPresenter Visibility = "Visible" Margin="15,0,0,0"
DataContext="{Binding View, RelativeSource={RelativeSource FindAncestor,ListView,1}}"
Columns="{Binding Columns}"
ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeaderStyleABCD}"
ColumnHeaderTemplate="{Binding ColumnHeaderTemplate}"
ColumnHeaderTemplateSelector="{Binding ColumnHeaderTemplateSelector}"
AllowsColumnReorder="{Binding AllowsColumnReorder}"
ColumnHeaderContextMenu="{Binding ColumnHeaderContextMenu}"
ColumnHeaderToolTip="{Binding ColumnHeaderToolTip}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<ItemsPresenter Margin = "15,0,0,0" />
</StackPanel>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: Further the column headers shall presented with custom colors for each column.
It can be solved through the ColumnHeaderContainerStyle. If you set an empty Template at GridView.ColumnHeaderContainerStyle and use your styled GridViewColumnHeaderStyleABCD for your GroupItem it should work.
I tried the following, that only displays column headers at the group items with customized Background.
<ListView BindingGroup="{Binding Name}" ItemsSource="{Binding Source={StaticResource TestItems}}">
<!-- ### custom coloring column headers ### -->
<ListView.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Background" Value="{Binding Path=Column.(YourNamespace:BgHelper.CustomBackground), RelativeSource={RelativeSource Self}}" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<!-- Empty: ListViews header shows nothing -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ColumnHeaderContainerStyle>
<!-- ### custom coloring column headers ### -->
<GridViewColumn DisplayMemberBinding="{Binding Parameter0}" Header="Par0" YourNamespace:BgHelper.CustomBackground="Pink" />
<GridViewColumn DisplayMemberBinding="{Binding Parameter1}" Header="Par1" YourNamespace:BgHelper.CustomBackground="Green" />
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Expander Margin="2">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" # " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Expander.Header>
<StackPanel Orientation="Vertical">
<GridViewHeaderRowPresenter Margin="15,0,0,0"
Columns="{Binding Columns}"
DataContext="{Binding View, RelativeSource={RelativeSource FindAncestor, ListView, 1}}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Visibility="Visible" />
<ItemsPresenter Margin="15,0,0,0" />
</StackPanel>
</Expander>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
To customize your column header colors you could use an AttachedProperty as follows:
namespace YourNamespace
{
public class BgHelper
{
#region Fields
public static DependencyProperty CustomBackgroundProperty =
DependencyProperty.RegisterAttached("CustomBackground",
typeof (SolidColorBrush),
typeof (BgHelper),
new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Transparent)));
#endregion
#region Public Methods
public static SolidColorBrush GetCustomBackground(DependencyObject element)
{
return (SolidColorBrush) element.GetValue(CustomBackgroundProperty);
}
public static void SetCustomBackground(DependencyObject element, SolidColorBrush value)
{
element.SetValue(CustomBackgroundProperty, value);
}
#endregion
}
}
Then I extended my example above with setting the CustomBackground and using it at GridViewColumnHeader style. I marked the new/edited lines with comments.
#WPFGermany was correct. However, in my original question I forgot to add that for the headers within the GroupStyle I also needed to show different background colors for some of the column headings. I was able to get this to work by duplicating all of the columns in the GroupStyle and pointing each ColumnHeaderStyle to a unique color. Perhaps there is a better way but for now this works for me. Here is the partial GroupStyle to illustrate:
<Style x:Key="GroupingNcpCheckStyleRoot" TargetType="{x:Type GroupItem}" BasedOn="{StaticResource GroupingBaseRoot}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsExpanded="{Binding IsExpandedData, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Mode=OneTime}" Margin="2">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="HeaderCheckBox" Margin="0,0,6,0" IsChecked="True"></CheckBox>
<TextBlock Text=" # "/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</Expander.Header>
<StackPanel Orientation="Vertical">
<GridViewHeaderRowPresenter Margin="15,0,0,0"
DataContext="{Binding View, RelativeSource={RelativeSource FindAncestor, ListView, 1}}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Visibility="Visible" >
<GridViewHeaderRowPresenter.Columns>
<!--NOTE: must explicitly create the collection-->
<GridViewColumnCollection>
<GridViewColumn Header=" " Width="60" >
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource GridViewColumnHeaderStyleTEST1}">
<Setter Property="Background" Value="{StaticResource TargetHeaderColor}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="-1,0,-1,0" />
</Style>
</GridViewColumn.HeaderContainerStyle>
<GridViewColumn.CellTemplate>
<DataTemplate >
<TextBlock HorizontalAlignment="Left" Text="{Binding Path=Id, StringFormat='# {0}'}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header=" Show " >
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource GridViewColumnHeaderStyleTEST1}">
<Setter Property="Background" Value="{StaticResource DifferentHeaderColor}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="-1,0,-1,0" />
</Style>
</GridViewColumn.HeaderContainerStyle>
<GridViewColumn.CellTemplate>
<DataTemplate >
<CheckBox IsChecked="{Binding Path=IncludeInReport}" HorizontalAlignment="center"></CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I have my own custom combobox with last item as button with command:
Code:
public class CustomComboBox : ComboBox
{
public static readonly DependencyProperty ButtonCommandProperty =
DependencyProperty.Register("ButtonCommand", typeof (ICommand), typeof (CustomComboBox), null);
public ICommand ButtonCommand
{
get { return (ICommand) GetValue(ButtonCommandProperty); }
set { SetValue(ButtonCommandProperty, value); }
}
}
Styles:
<Style TargetType="{x:Type controls:CustomComboBox}">
<Style.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Height" Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="{TemplateBinding Content}" Background="Transparent" Foreground="#CCCCCD" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:CustomComboBox}">
<StackPanel>
<ComboBox
SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:CustomComboBox}},
UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ItemsSource, Mode=OneWay,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:CustomComboBox}},
UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock Style="{StaticResource TextBlockDimmed}" Text="{Binding Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger
Binding="{Binding Converter={converters:ComboBoxItemIndexToStringConverter},
RelativeSource={RelativeSource Self}}" Value="IsLastItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<Button Content="{Binding}"
Command="{Binding ButtonCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:CustomComboBox}}}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using:
<controls:CustomComboBox Grid.Column="1"
SelectedItem="{Binding Path=SelectedAreaName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ButtonCommand="{Binding CreateNewAreaCommand}"
ItemsSource="{Binding AreasNamesList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
When I try to call button command in programm (click on the button) more than once then I got an error message:
'Specified element is already the logical child of another element. Disconnect it first.'
I guess the problem in XAML styles, but i'm not sure in what the problem exaclty is.