MaterialDesignThemes ComboBox Selected Item template issue - c#

I'm working on styling a WPF ComboBox so that the ComboBoxItems have some additional data. The items look great when in the drop down, but once selected, the displayed item is not stretched/filling the ComboBox- it's all smushed to the left. I've done enough digging to figure out this is related to the MaterialDesign Theme being applied to the control. Without MeterialDesign being referenced in a demo project, the code works as anticipated.
<ComboBox Width="150"
Margin="2"
HorizontalContentAlignment="Stretch" <!-- No Effect //-->
materialDesign:HintAssist.Hint="Select Item"
ItemsSource="{StaticResource ExampleItems}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding DisplayText}" />
<Ellipse Grid.Column="1" Width="10" Height="10" Fill="{Binding Color}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
<!-- No Effect //-->
<!--<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource MaterialDesignComboBoxItemStyle}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ComboBox.ItemContainerStyle>-->
</ComboBox>
I've tried pretty much everything I can without luck- Including various controls inside the DataTemplate, stack panel, dock panel, etc....
I've created a minimum reproducible example here: ComboBoxDemo Project
I've included the ComboBox Style I pulled from Blend, to try to dig into what MaterialDesign is doing on top of the normal template. I see that there is an ItemContainerStyle for the selected item, but it looks like it's binding the HorizontialContentAlignment up the chain. Manually setting that to Stretch did not help.
So Hopefully a Xaml guru out there can pinpoint the issue...

Related

WPF - Binding custom DataGridTextColumn template's Content property to parent's property

First of, I am coming back to WPF after several years of leaving it behind, I knew a little of it before and develop a few windows but now I am beyond rusty.
I am trying to build a DataGrid with filter headers, now I understand that there isn't a ready made control for that and needs to be created, which I have started using a Template.
My template consists of a Label control to the left which contains the title of the header, and a DatePick control to the right which I will use as part of my filtering process. I am trying to get Label.Content property inside my template to pick the DataGridTextColumn.Header property value of template parent.
I have tried RelativeSource, TemplatedParent and everything else there is, I also couldn't find any post on here that described a similar issue to mine nor a solution. Any help would be greatly appreciated. Thanks.
My code
<UserControl x:Class="CustomControls.ReportsListingControl"
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"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="600">
<UserControl.Resources>
<Style x:Key="ColumnHeaderStyle1" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Grid Width="200" Height="35">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Width="50"
Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridTextColumn}}, Path=Header}" />
<DatePicker Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Width="30"
BorderThickness="0" Text="" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<DataGrid Name="DataGrid1" >
<DataGrid.Columns>
<DataGridTextColumn HeaderStyle="{StaticResource ColumnHeaderStyle1}" Header="The Text I want displayed in my template label" />
</DataGrid.Columns>
</DataGrid>
</Grid>
Bind to the DataContext itself:
<Label ... Content="{Binding}" />
The DataContext of a DataGridColumnHeader is the Header object itself, i.e. the string in your case.

Weird issue with WPF TreeView when using mouse wheel to scroll

So, I've been working on a legend for our map using a WPF treeview to display the groups and layers.
I've gotten it working and displaying just fine, but when I scroll the treeview with the mousewheel, the control starts flickering and the vertical scrollbar for the tree keeps resizing up and down.
The treeview layout is like this:
Group
Layer
Layer sub items
Layer
Layer sub items
Layer
Layer sub items
Group
Layer
etc...
The Group and Layer nodes are tree view items, but the layer sub items are contained within an items control. The layer sub items are not meant to be expanded/contracted, or selected and thus must remain static under the layer node, thus the items control seemed like a sensible choice.
When I scroll with the mouse wheel all the way to the top or bottom of the tree view, the scrollbar starts flicking and resizing, the last few elements of the items control flickers in and out of view (when it shouldn't be in view at all), and sometimes, the tree view will actually scroll back and forth.
If I remove the items control, everything works as it's supposed to. And when I add it back in, it messes up.
Also, if I grab the scroller thumb with the mouse and drag it, everything works fine. No jumping around.
Here's the resource XAML for the control:
<views:DynamicLegendNodeTemplateSelector x:Key="LegendTemplateSelector">
<views:DynamicLegendNodeTemplateSelector.GroupTemplate>
<HierarchicalDataTemplate DataType="{x:Type legend:IDynamicMapLegendGroup}">
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding Converter="{StaticResource LegendNode}">
<Binding Path="Groups"/>
<Binding Path="LegendLayers"/>
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
<Grid>
<StackPanel Orientation="Horizontal">
<CheckBox Focusable="False" IsChecked="{Binding IsVisible}" VerticalAlignment="Center">
<TextBlock Text="{Binding DisplayName}" VerticalAlignment="Center"/>
</CheckBox>
</StackPanel>
</Grid>
</HierarchicalDataTemplate>
</views:DynamicLegendNodeTemplateSelector.GroupTemplate>
<views:DynamicLegendNodeTemplateSelector.LayerTemplate>
<HierarchicalDataTemplate DataType="{x:Type legend:IDynamicMapLayerLegendItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Focusable="False" IsChecked="{Binding IsVisible}" VerticalAlignment="Center">
<TextBlock Text="{Binding LayerCaption}" VerticalAlignment="Center"/>
</CheckBox>
<ItemsControl Grid.Row="1"
Margin="16,0,0,0"
BorderThickness="0"
Background="Transparent"
ItemsSource="{Binding LegendItems, IsAsync=True}"
HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
MouseWheel="ItemControls_MouseWheel"
ScrollViewer.CanContentScroll="False"
MouseUp="ItemsControl_MouseUp">
<ItemsControl.Template>
<ControlTemplate>
<ItemsPresenter/>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Width="20" Height="20" Stretch="UniformToFill" Source="{Binding Symbol}"/>
<Label Grid.Column="1" Content="{Binding Label}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</HierarchicalDataTemplate>
</views:DynamicLegendNodeTemplateSelector.LayerTemplate>
</views:DynamicLegendNodeTemplateSelector>
<Style x:Key="TreeItemStyle" TargetType="TreeViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<EventSetter Event="MouseUp" Handler="TreeViewItem_MouseUp"></EventSetter>
</Style>
And here's the treeview:
<TreeView x:Name="LegendHierarchy"
MinWidth="200"
ItemsSource="{Binding LegendItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:DynamicArcGisRuntimeMapLegendView}}}"
ItemContainerStyle="{StaticResource TreeItemStyle}"
ItemTemplateSelector="{StaticResource LegendTemplateSelector}" />
This code is using .NET 4.5 in Visual Studio 2015 if that matters.
Regardless, does anyone know what might be causing the problem?
Thanks
So, it goes to show that an attempt at a good nights sleep is helpful.
Apparently, all I had to do was set
VirtualizingPanel.VirtualizationMode="Recycling"
On the treeview control and it starting working.
Here's the full tree view XAML:
<TreeView x:Name="LegendHierarchy"
MinWidth="200"
ItemsSource="{Binding LegendItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:DynamicArcGisRuntimeMapLegendView}}}"
ItemContainerStyle="{StaticResource TreeItemStyle}"
ItemTemplateSelector="{StaticResource LegendTemplateSelector}" UseLayoutRounding="True" ScrollViewer.CanContentScroll="True" HorizontalContentAlignment="Stretch"
VirtualizingPanel.VirtualizationMode="Recycling"/>
I hope this helps others.

WPF: Style ToolTip with Image

Is it possible to create a style for ToolTip that would place an image next to the Item on which the tool tip resides and then show the tool tip text when the user hovers over the image? Something like this:
Currently I am doing a StackPanel to add the image with the tool tip like so:
<StackPanel Orientation="Horizontal">
<CheckBox Content="Reload Employee Data"
IsChecked="{Binding AdjustmentSettings.ReloadEmployeeData}"
Grid.Row="0"
Grid.Column="0">
</CheckBox>
<Image Source="/DelphiaLibrary;Component/Resources/info.ico"
ToolTip="Check if you want to re-upload ...."/>
</StackPanel>
EDIT
Just to clarify, I am looking for a way to style ToolTip such that if I define ToolTip on any object (i.e., Button, CheckBox, etc.) the info image is shown and the tool tip text is placed on this info image.
I would like to be able to do something like this and still get the same as the stack panel above:
<CheckBox Content="Reload Employee Data"
IsChecked="{Binding AdjustmentSettings.ReloadEmployeeData}"
Grid.Row="0"
Grid.Column="0"
ToolTip="Blah blah blah..."
Style="{StaticResource ToolTipImageStyle}">
</CheckBox>
And be able to apply this ToolTipImageStyle to any control (i.e., Button, CheckBox, TextBox, etc.). If that isn't possible can I style an individual control and just create different styles for different controls (one for buttons, another for TextBlock, etc.)?
This should do it. I couldn't figure out the color so just change that.
Source 1
Source 2
<Image Source="/DelphiaLibrary;Component/Resources/info.ico" Width="25" Height="25">
<Image.ToolTip>
<ToolTip Background="LightBlue">
<TextBlock Width="200" TextWrapping="WrapWithOverflow">
Check if you want to re-upload table foxpro.hrpersnl from the source. <LineBreak />
Leave unchecked to use existing data that has been previously uplaoded.
</TextBlock>
</ToolTip>
</Image.ToolTip>
</Image>
Update 1:
Source 1
In the App.xaml add this:
<Application.Resources>
<Style TargetType="{x:Type ToolTip}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}" >
<TextBox Background="LightBlue" Width="200" TextWrapping="WrapWithOverflow" Text="{TemplateBinding ToolTip.Content}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Then in your XAML file change to:
Note: This will work with all object's tool tips.
<Image Source="Images/MenuImageZoomOut.png" Width="25" Height="25"
ToolTip="Check if you want to re-upload table foxpro.hrpersnl from the source. Leave unchecked to use existing data that has been previously uplaoded." />
The image:
If this doesn't work, try this: Source

ListView disable right tapped selection style

I am trying to disable the right click functionality of my items inside a list view. I have tried handling the RightTapped event and setting the e.handled value to true. This has covered most of the list view's area however if I right click on the borders of the list view item, this selection style is still applied. I want the user to still be able to use the left click and apply the list selected styling. It is just the right click I want to disable.
Here is what I have tried so far:
<ListView
ItemsSource="{Binding MyItems}"
ItemClick="OnItemClicked"
IsItemClickEnabled="True"
SelectionMode="Multiple"
CanDragItems="True"
DragItemsStarting="OnDragItemsStarting"
RightTapped="OnRightTapped"
IsRightTapEnabled="False">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="-1,3,-1,0" />
<Setter Property="IsRightTapEnabled" Value="False"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent" RightTapped="OnRightTapped" HorizontalAlignment="Left" Height="100" Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ImagePath}" Width="55" Height="55" Margin="0,0,0,1"/>
<Image Margin="20,0,0,22" Grid.Column="0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="20" Height="20" Source="smallImage.png"/>
<StackPanel VerticalAlignment="Center" Margin="30,0,0,0" Grid.Column="1">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" Foreground="{Binding IsOnline, Converter={StaticResource BooleanToColorConverter}}" Style="{StaticResource BaseTextBlockStyle}" FontSize="20" Height="60"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is the code for the RightTapped handler:
private void OnRightTapped(object sender, RightTappedRoutedEventArgs e)
{
e.Handled = true;
}
Edit: When I click on the borders of an Item in the ListView the OnRightTapped event is not being fired. What could be swallowing this event?
By playing with the background colors of the items inside my ListView.ItemTemplate, I found that my TextBlock was not covering the whole area of the row. By setting the Column width to the exact size of the ListView and setting the RightTapped event handler on this Grid I was able to cover all areas of right clicking. I still do not know why the RightTapped handler was not being fired for the ListView itself but this was a sufficient solution for what I needed.

ListView in Windows Phone 8.1 Wobbles while scrolling though long list (XAML)

I'm having issues with scrolling through ListViews in my Windows Phone 8.1 App. Short lists scroll just fine, scrolling smoothly however as soon Virtualization kicks in the entire ListView "wobbles" to the left slightly, but noticeable enough to be annoying.
I've tried remove all the transitions to no effect as well as having items load incrementally to no success. Setting the item panel to a StackPanel (removing virtualization) fixes the issue but is not preferable.
My listviews are binding to a property in the DefaultViewModel that comes with the Basic Page Template.
What am I doing wrong and what are causing my ListViews to exhibit this behavior?
XAML:
<ListView x:Name="searchResultsList" IsItemClickEnabled="True" ItemClick="ListView_ItemClick" ItemsSource="{Binding searchResults}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,0,0,20" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Width="80" Height="80">
<Image Source="{Binding Image}" />
</Border>
<StackPanel Grid.Column="2">
<TextBlock Text="{Binding PodcastTitle}" TextWrapping="WrapWholeWords" FontSize="{StaticResource TextStyleExtraLargeFontSize}" />
<TextBlock Text="{Binding LastUpdated, Converter={StaticResource dateConverter}}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
<TextBlock Text="{Binding PodcastArtist}" TextWrapping="WrapWholeWords" Style="{ThemeResource ListViewItemContentTextBlockStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
So this seems to be an OS issue, as evidenced in this thread on the MS forums: http://social.msdn.microsoft.com/Forums/en-US/9a363d33-5760-4d38-9c81-84259c4edcbe/listview-jiggles-horizontally-when-large-item-about-to-scroll-in-or-out-in-windows-phone-81-preview?forum=WindowsPhonePreviewSDK&prof=required.
The issue does indeed lie in virtualization, with items that have no fixed width. Using star as the width or making the horizontal alignment stretch won't work so the only solution that takes account orientation and resolution was to bind the width to the ListView's container's ActualWidth property:
<Grid x:name="contentRoot" Margin="19,9.5,19,0">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width={Binding ActualWidth, ElementName=contentRoot} />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
The first element in the listview is not displayed because the ActiualWidth of the Grid is 0 in the first second, when loaded the page. This is the solution, that's working for me:
<Grid x:Name="contentRoot" Margin="20">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid MinWidth="{Binding ActualWidth, ElementName=contentRoot}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
This is a really annoying bug. I can't understand why this is not fixed since years now.
Imho stretching items in a vertical scrolling listview is a very basic feature and should work 100%.
A possible workaround is also this snipped, which should also be aware of size changes :
public class StrechItemsListView : ListView
{
public StrechItemsListView()
{
SizeChanged += StrechItemsListView_SizeChanged;
}
private void StrechItemsListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (ItemsPanelRoot != null)
{
ItemsPanelRoot.Width = e.NewSize.Width;
}
}
}
Changing the xaml only to a custom listview type is less work and cleaner then edit every datatemplate etc. Just my 2 cents.
My Practice seems to work. At least in WP8.1.
Just set the ItemsPanelTemplate in the <ListView></ListView> Block explicitly, but not use
Style="{StaticResource ListViewStyle1}" or something else.
Sample Code:
<ListView ItemsSource="{Binding RadioList}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollMode="Auto">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="10,3,10,0">
<TextBlock Text="{Binding RadioName}" FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" Width="{Binding PhoneWidth}"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
The HorizontalContentAlignment and Width of VirtualizingStackPanel settings are used to center the content in the ListView .You can move these settings freely.I don't know why, but it does work.
This was fixed on Windows 10 for Windows 8.1 apps

Categories

Resources