WPF ListBox WrapPanel: MouseOver and SelectedItem transparant - wpf

I have the following Listbox:
<ListBox Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding MyItems}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True">
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
But when I do a mouseover or select an item, the item is "blue".
I want it to be transparant.
Also I want the item to be underlined if selected.
MyItem is an observableCollection of myItem:
public class MyItem
{
public string Key { get; set; }
public bool Selected{ get; set; }
}

You can for example simply setup the default style for the ListBoxItem at the top of your xaml file or ideally inside of your resources xaml file. You must override default control template in order to achive that. You don't have to setup triggers directly. Here's example. Have fun.
<Window x:Class="StackPoC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackPoC"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ListBox ItemsSource="{Binding Collection}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT
I haven't read the part about underline on Selected*. Well.. You already know that you had to create custom control template in order to get rid of the selection. I wont write the code for you but I will give you an idea on how to do that ;) Create Triggers inside of a node ControlTemplate.Triggers according to the IsSelected property and then use Setter in order to setup your desired appearance. Good luck.

Related

WPF Setting both DataTemplate and ControlTemplate on a control does not work

I am obviously missing something very basic here. I have found similar questions but from none of the answers I was able to comprehend what I am doing wrong.
When I set ControlTemplate, my DataTemplate is not picked up.
I have created a very simple example of my problem:
<Window x:Class="WpfTesterProject.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTesterProject"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Person}">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding Content}">
<ContentControl.Template>
<ControlTemplate>
<Border BorderBrush="Blue" BorderThickness="2">
<ContentPresenter />
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
</Window>
What I want to do is select user-defined data template loaded at runtime, but also I want to, for example, wrap every single element in border, no matter what the user template is or even if he did not specify any templates at all.
From what I have read from similar questions, I have to use <ContentPresenter /> in the ControlTemplate, but the result is the same as if I remove it - only border is shown.
I reproduced your application. It seems the problem is in the TargetType property of the ControlTemplate:
<ContentControl Content="{Binding}">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<Border BorderBrush="Blue" BorderThickness="2">
<ContentPresenter />
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>

Trouble with setting both DataTemplate and ControlTemplate to Map Pushpins in WPF

I am having trouble setting both DataTemplate and ControlTemplate to my bing map pushpins. I am using data binding which works to a point when i try to customize my pushpins by adding ControlTemplate.
My code:
<UserControl x:Class="BingMap.MapUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:viewPushpins="clr-namespace:Program.Map_Control.ViewPushpins">
<UserControl.DataContext>
<viewPushpins:MapViewPushpins/>
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate x:Key="PushpinDataTemplateP">
<m:Pushpin Location = "{Binding MapLocationP}" ToolTip="{Binding MapTooltipTextP}"/>
</DataTemplate>
<ControlTemplate x:Key="PushpinControlTemplateP">
<Grid>
<Ellipse Fill="Green" Width="15" Height="15" />
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<m:Map Name="myMap"
CredentialsProvider="..."
ZoomLevel="1"
Center="30,-100"
Mode="AerialWithLabels"
MouseLeftButtonUp="Map_Left_Click_Up">
<m:MapItemsControl
Template="{StaticResource PushpinControlTemplateP}"
ItemTemplate="{StaticResource PushpinDataTemplateP}" MouseLeftButtonUp="Map_Left_Click_Up"
ItemsSource="{Binding MapLocationsP}"/>
</m:Map>
</Grid>
</UserControl>
This code works if I remove the line:
Template="{StaticResource PushpinControlTemplateP}"
but then don't get my customized pushpin.
Any ideas on how can I fix this?
By setting MapItemsControl.Template, you're specifying a template for the MapItemsControl itself, not the items it produces. You can set the template for individual items produced by an ItemsControl indirectly via the ItemContainerStyle:
<Style x:Key="PushPinStyle">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<!-- your template goes here -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<m:MapItemsControl ItemContainerStyle="{StaticResource }" ...>
I see where i got this wrong. As already mentioned by Kent, the line
Template="{StaticResource PushpinControlTemplateP}"
shouldn't be in MapItemsControl.
I solved my problem with moving this line of code to Resources so they look like this:
<UserControl.Resources>
<ControlTemplate x:Key="PushpinControlTemplateP">
<Grid>
<Ellipse Fill="Green" Width="15" Height="15" />
</Grid>
</ControlTemplate>
<DataTemplate x:Key="PushpinDataTemplateP">
<m:Pushpin Location = "{Binding MapLocationP}" ToolTip="{Binding MapTooltipTextP}" Template="{StaticResource PushpinControlTemplateP}"/>
</DataTemplate>
</UserControl.Resources>

How To improve wpf user control performance?

I have a usercontrol, and when I have lots of that in a window, it takes long time to get loaded.
Will it get better if I change it to a customcontrol or maybe a DataTemplate with a class and attached properties?
any ideas would be greatly appreciated.
Edited:
this is my control:
<UserControl
x:Class="Pouyansoft.WPF.MVVM.Control.Common.View.DataGridSelectorControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="dataGridSelector"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" >
<UserControl.Resources>
<CollectionViewSource Source="{Binding DataCollection.Source}" x:Key="theSource"/>
<Style x:Key="DataGridColumnHeaderStyle1" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{TemplateBinding Content}"
HorizontalAlignment="Center" />
<TextBox x:Name="txtSearch" Grid.Row="1" HorizontalAlignment="Stretch"
BorderThickness="1" TextChanged="TextBox_TextChanged" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<DataGrid x:Name="grd"
ItemsSource="{Binding Source={StaticResource theSource}}"
AutoGenerateColumns="False"
ColumnHeaderStyle="{DynamicResource DataGridColumnHeaderStyle1}"
PreviewKeyDown="grd_PreviewKeyDown"
SelectedIndex="{Binding SelectedIndex}"
behavior:MouseDoubleClick.Command="{Binding MouseDoubleClickCommand}"
PreviewMouseLeftButtonUp="grid1_PreviewMouseLeftButtonUp"
GridLinesVisibility="Vertical">
</DataGrid>
</Grid>
and some code in the code behind.(and actually all the other control has the same behavior)
First thing, don't use DynamicResource use StaticResource -
use
ColumnHeaderStyle="{StaticResource DataGridColumnHeaderStyle1}"
in place of
ColumnHeaderStyle="{DynamicResource DataGridColumnHeaderStyle1}"
Second thing is to check for binding errors in your Output window, try and fix as many as you can.
Also, I don't see any benefit of using CollectionViewSource (as you are not doing any Sorting, Filtering, Grouping); If it's not necessary to use CollectionViewSource, you can directly bind the DataGrid's ItemSource to your DataCollection.Source.

Binding in CustomControl

I have created a custom control which is (among other things) able to display many expanders in an ItemsControl.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"> <Style TargetType="{x:Type NxTabControl:NxCategoryControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type NxTabControl:NxCategoryControl}">
<ScrollViewer x:Name="contentScrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel HorizontalAlignment="Stretch" DockPanel.Dock="Bottom" VerticalAlignment="Stretch" Background="Transparent">
<ItemsControl ItemsSource="{TemplateBinding Content}">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<Border>
<ItemsPresenter/>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>
The ItemsControl is binding to :
ItemsSource="{TemplateBinding Content}
Which is a DP in the class:
public class CategoryControl : ItemsControl
{
public ObservableCollection<Expander> Content
{
get { return (ObservableCollection<Expander>)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(ObservableCollection<Expander>), typeof(CategoryControl), new FrameworkPropertyMetadata(new ContentCollection(), FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsParentMeasure)); }
I am using my custom control in a user Control by setting the content Property and adding expanders to it:
<NxTabControl:NxCategoryControl x:Name="catControl" DockMode="Top" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Green">
<TabControl:CategoryControl.Content>
<Expander Margin="0 3 0 3" IsExpanded="True" Header="Adresse" >
<ScrollViewer x:Name="ScrollViewerAdresse" HorizontalAlignment="Stretch" ockPanel.Dock="Left">
<Grid Width="{Binding ElementName=ScrollViewerAdresse, Path=ActualWidth, Converter={StaticResource HalfWidthConverter}}">
</Grid>
</ ScrollViewer>
</Expander>
<Expander>
</Expander>
<Expander Header={Binding ExpanderHeader}>
</Expander>
</TabControl:CategoryControl.Content>
My problem in this context is that I am not able to set this binding:
Grid Width="{Binding ElementName=ScrollViewerAdresse, Path=ActualWidth}"
And also no other binding that goes to an “ElementName”. I am e.g also binding to XamDataGrids.ActiveRecords by their name and other Elements. None of the bindings works.
Snoop tells me for the Width Property of the Grid:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=ScrollViewerAdresse'.
BindingExpression:Path=ActualWidth; DataItem=null; target element is 'Grid'; target property is 'Width' (type 'Double')
Other bindings I am using in my expanders, binding to the ViewModel of the usercontrol work though, e.g.:
Header={Binding ExpanderHeader}
Any help would be welcome! Thx!

WPF - Binding to current item from within group header style

I'm something of a WPF noob so please take it easy on me ;-)
I am trying to create a grouped DataGrid (WPF toolkit version).
I have successfully created the data source, the DataGrid itself, the required CollectionViewSource and the Style for the group header (which uses an expander).
I want to group by a property called 'Assign_To' and have the relevant value (the value that the grouped items share) show up in the header. However, I cannot work out how to bind to the current group/item in order to return its Assign_To property.
The closest I have got (shown below) is binding to the overall CollectionViewSource, which returns a fixed value for Assign_To. What would be the proper way to bind to the current item/group in order to return the correct value for 'Assign_To'?
Hope someone can help. Thanks!
Andy T.
Here's the source...
<Window DataContext="{Binding Source={StaticResource SampleDataSource}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DataGridTest.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480" mc:Ignorable="d">
<Window.Resources>
<CollectionViewSource x:Key="CVS" Source="{Binding MyData}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Assign_To"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Assign To: "/>
<TextBlock Text="{Binding Source={StaticResource CVS}, Path=Assign_To}"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<dg:DataGrid
ItemsSource="{Binding Source={StaticResource CVS}}"
SelectionUnit="CellOrRowHeader"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserResizeRows="False">
<dg:DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<dg:DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</dg:DataGrid.GroupStyle>
</dg:DataGrid>
</Grid>
</Window>
Thanks for your reply. I really appreciate it and will check it out to see if it works.
Anyway, as it turns out, after some poking and prodding, I have worked it out using XAML only. What I had been missing was the fact that each item the group header is bound to is a GroupItem and that the default DataContext of a GroupItem is a CollectionViewGroup. In turn, a CollectionViewGroup has an Items property, which is a collection and I can therefore get the Assign_To value of the first item in the collection and use that in my header text. Like this:
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Assign To: "/>
<TextBlock Text="{Binding Items[0].Assign_To}"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
binding settings depend on the type of the Assign_To property. The simplest settings which could probably work for you would be:
<TextBlock Text="Assign To: "/>
<TextBlock Text="{Binding Name}"/>
pls, check if an example below would work for you; also this link WPF Toolkit DataGrid Part IV: TemplateColumns and Row Grouping might be helpful for you
code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var dataProvider = (CollectionViewSource)FindResource("CVS");
dataProvider.Source = Test.GetTests();
}
}
public class Test
{
public string Assign_To { get; set; }
public string Test0 { get; set; }
public int Test1 { get; set; }
public static List<Test> GetTests()
{
List<Test> tests = new List<Test>();
tests.Add(new Test { Assign_To = "a", Test0 = "aaaa", Test1 = 1 });
tests.Add(new Test { Assign_To = "a", Test0 = "bbbb", Test1 = 1 });
tests.Add(new Test { Assign_To = "b", Test0 = "cccc", Test1 = 2 });
return tests;
}
}
xaml:
<Window.Resources>
<CollectionViewSource x:Key="CVS" >
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Assign_To"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Assign To: "/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<DataGrid
ItemsSource="{Binding Source={StaticResource CVS}}"
HorizontalScrollBarVisibility="Hidden" SelectionMode="Extended"
AutoGenerateColumns="False"
Name="dataGrid1">
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Test0" Binding="{Binding Path=Test0}" />
<DataGridTextColumn Header="Test1" Binding="{Binding Path=Test1}" />
</DataGrid.Columns>
</DataGrid>
</Grid>

Resources