Setting user control position - c#

Hello Stackoverflowers,
I'm using an ItemsControl and my elements are all drawn on the top left corner, which create to a gap between the actual position and the mouse position (where my elements should be). Relevant mouse positions are saved in view model.
<ItemsControl
ItemsSource="{Binding OverlayElementsList}"
Background="Transparent"
BorderBrush="Black"
BorderThickness="2">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding ElementName=X, Path=Client.OverlayElement.StartPoint}" />
<Setter Property="Canvas.Top" Value="{Binding ElementName=Y, Path=Client.OverlayElement.StartPoint}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type elements:OverlayElement}">
<ContentControl Content="{Binding View}" />
</DataTemplate>
</ItemsControl.Resources>
Here is one of the possible View binded in the ItemsControl.Resources :
<UserControl x:Class="Client.ImageOverlayElementView"
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:local="clr-namespace:Genetec.CS.OverlayModule.Client"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:ImageOverlayElement}">
<Grid>
<Image
Source="{Binding ImageSource}"
Height="{Binding Height}"
Width="{Binding Width}"
Canvas.Left="{Binding StartPoint}"
Canvas.Top="{Binding EndPoint}"/>
</Grid>
</UserControl>
The Canvas.Left and Canvas.Top properties seem to be simply ignored, why ?

Related

Override a specific command button background-color in MVVM using a Shared Resource XAML

How can I change the back-ground color of a specific button without making a new set of styles in the SharedResources.xaml?
Button Picture
In this picture below, it shows three buttons using the same styles from the SharedResource.xaml. My goal is to make only the second button change it's color from "WhiteSmoke" to "Purple/Color of my choice".
Button Picture
MainWindowViewModel.cs
These buttons are styled in the SharedResources.xaml.
protected override void CreateCommands()
{
this.Commands.Add(new CommandViewModel("First Button", new DelegateCommand(p => this.BtnOne())));
this.Commands.Add(new CommandViewModel("Second Button", new DelegateCommand(p => this.BtnTwo())));
this.Commands.Add(new CommandViewModel("Third Button", new DelegateCommand(p => this.BtnThree())));
}
SharedResources.saml
The Background color is "WhiteSmoke". This is the color that I want to override just for that Second Button (or any specific button) without the need of creating another set of styles in the SharedResources.xaml.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:System">
<!-- Navigation Style for Buttons -->
<DataTemplate x:Key="CommandsTemplate">
<ItemsControl ItemsSource="{Binding}" HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Path=Command}" Content="{Binding Path=DisplayName}" Width="180" Height="40" BorderThickness="1" FontSize="20" FontStyle="Oblique" Background="WhiteSmoke" Margin="8,8,0,0">
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
MainWindow.xaml
The buttons are bound in the "HeaderedContentControl's" "Content" and the Styles of the buttons are bounded in the "ContentTemplate".
<Window x:Class="System.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:System"
mc:Ignorable="d" Title="{Binding Path=DisplayName}" Height="550" Width="1080">
<!-- Connect this xaml to SharedResources -->
<Window.Resources>
<ResourceDictionary Source="SharedResources.xaml" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="4" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Height="60">
<HeaderedContentControl Content="{Binding Path=Commands}" ContentTemplate="{StaticResource CommandsTemplate}" />
</Border>
<Border Grid.Row="2">
<HeaderedContentControl Content="{Binding Path=ViewModels}" ContentTemplate="{StaticResource WorkspacesTemplate}" />
</Border>
</Grid>
Just use the BasedOn attribute to inherit either an exist resource style or the default one:
<Window.Resources>
<!-- Default button style is blue text on a white background -->
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Background" Value="White" />
</Style>
</Window.Resources>
<!-- Button with blue text on a yellow background -->
<Button Content="Hello World" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Yellow" />
</Style>
</Button.Style>
</Button>

Group heading is not displayed after grouping in ItemsControl

I'm trying to group my ObservableCollection using CollectionViewSource, it seems to work for items but it's not showing the bind property value for GroupBox.
Here is what I'm trying:
I've List<Object> containing properties Description, Season. I want to group by Season. Here is my xml:
<mah:MetroWindow x:Class="eCatalog_Launcher.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:eCatalog_Launcher"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
mc:Ignorable="d"
Title="eCatalog Launcher"
WindowState="Maximized"
Loaded="MetroWindow_Loaded"
Closing="MetroWindow_Closing">
<Window.Resources>
<CollectionViewSource x:Key="catalogsBySeasons"
Source="{Binding Path=Catalogs, Mode=TwoWay}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Season" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Source={StaticResource catalogsBySeasons}}">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Season}">
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<mah:Tile Title="{Binding Description}"
Tag="{Binding}"
Style="{StaticResource SmallTileStyle}"
Click="Tile_Click">
<iconPacks:PackIconMaterial Width="32"
Height="32"
Margin="0, -30, 0, 0"
Kind="{Binding Kind}">
</iconPacks:PackIconMaterial>
</mah:Tile>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
It's showing the Season value as GroupBox Heading.
Is there anything wrong?
You should bind to the Name property of the group:
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Name}">
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
This should display the actual value of the Season property that you group by.

Possible to display images in a ListBox with multiple rows

I am trying to get images in a Listbox to display in a certain way.
Listbox now:
How i want:
As you can see i want the scroll bar to be down the side and there to be multiple columns and rows depending on the size of the listbox.
Define WrapPanel as ListBox's ItemsPanel:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel ></WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Don't forget to set Width or MaxWidth to the wrap panel. Once max width is reached it will start placing content on new line...
use WrapPanel with Width set to a value. for an example run below code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525" >
<Window.DataContext>
<local:ParentViewModel />
</Window.DataContext>
<ListBox Height="auto" ItemsSource="{Binding MyList,Mode=TwoWay}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate" >
<Setter.Value>
<DataTemplate>
<Button Content="{Binding}" Padding="15,5" Margin="100,40,0,0"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=DataContext.RemoveButtonCommand}"
CommandParameter="{Binding}"
/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}},Path=ActualWidth}"
>
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
You will get both vertical and horizontal scrollbars. both adjusting according to height and width of window with the elements in listbox. (please bind your own listbox source)

Binding popup PlacementTarget to listbox SelectedItem

I have the following XAML (simplified):
<Grid>
<Popup Name="Popup" DataContext="{Binding ElementName=GameWheel, Path=SelectedItem}" PlacementTarget="{Binding SelectedItem}" Placement="Center" IsOpen="True">
<Image Source="{Binding ImagePath}" Width="100" />
</Popup>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel" ...>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<c:VirtualizingWrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="GamesWheelImage" ... />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
While the DataContext is correct and it shows me the right image in the popup, the placement is completely wrong. My intention is to have the popup cover the center of the SelectedItem in the listbox, but for some reason it's always placed in the center of the window.
Any ideas on how to get the placement for the selectedItem in the listbox so the popup always covers the center of the selected item? The closest I get it to place the image in the center of the listbox, but I'm not able to get it to cover just the selected item.
In my opinion you should create a specific template for the ListBoxItems which belong to the Listbox called GameWheel.
Just to give you a sample, I created a simplier version of your ListBox:
<Window x:Class="WpfApplication1.MainWindow"
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"
Title="MainWindow" Height="300" Width="400">
<Window.Resources>
<ControlTemplate x:Key="ListBoxItemWithPopup" TargetType="{x:Type ListBoxItem}">
<Border Name="border" Padding="2">
<Grid>
<Popup Name="popup" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Placement="Center" >
<TextBlock Margin="1" Background="White" Foreground="Black" Text="{TemplateBinding Content}" />
</Popup>
<ContentPresenter />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="popup" Property="IsOpen" Value="True"/>
<Setter TargetName="border" Property="Background" Value="Azure" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" Value="{StaticResource ListBoxItemWithPopup}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
</ListBox.Items>
</ListBox>
</DockPanel>
</Grid>
</Window>
As you can see the Popup is directly contained in the ListBoxItem template and it is showed using a Trigger.
I hope my sample can help you.

"CanContentScroll" property does not work elegantly with nested ScrollViewers

I have CanContentScroll property set to True in the parent Scrollviewer. This ScrollViewer is applicable to the entire Window. Now, this ScrollViewer has ItemsControl as its child. Each item in the ItemsControl is templated as an Expander and the content of this Expander contains another ItemsControl embedded in the child ScrollViewer. If I remove the child ScrollViewer, the Window content is scrollable, however, if I put it back in, I'm unable to Scroll.
I need the child ScrollViewer because I am limiting the height of the Expander content. When I scroll, the event is not being fired to the parent ScrollViewer in the Visual Tree. How and by using which event I can bubble it to the parent ScrollViewer in the Visual Tree?
This is my code:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="clr-namespace:AttributeSelector" xmlns:sys="clr-namespace:System;assembly=mscorlib"
MinHeight="350" MinWidth="525" MaxWidth="1200" MaxHeight="900" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight">
<sys:Boolean x:Key="BooleanTrue">True</sys:Boolean>
<sys:Boolean x:Key="BooleanFalse">False</sys:Boolean>
<behaviors:TextToHighlightedTextBlockConverter x:Key="TextToHighlightedTextBlockConverter" />
<behaviors:GroupNameToICollectionViewConverter x:Key="GroupNameToICollectionViewConverter" />
<LinearGradientBrush x:Key="LinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#E3E3E3" Offset="1"/>
<!--<GradientStop Color="#C0C0C0" Offset="1"/>-->
</LinearGradientBrush>
<Style x:Key="MainBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource ResourceKey=LinearGradientBrush}" />
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="SnapsToDevicePixels" Value="True" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True" Margin="10">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<!-- 3-4 TextBlocks/TextBoxes defined here -->
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="True">
<ItemsControl ItemsSource="{Binding UniqueGroups}" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" Style="{StaticResource ResourceKey=MainBorderStyle}">
<Expander x:Name="GroupExpander" Header="{Binding}" IsExpanded="True" Margin="5">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Background="Transparent" Margin="10,0,0,0"
FontWeight="DemiBold" FontSize="16" FontStretch="Expanded"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}"/>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Content>
<ScrollViewer Margin="20,5,10,5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<ItemsControl ItemsSource={Binding SubItems} ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxHeight="300" Orientation="Vertical" UseLayoutRounding="True" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
</ScrollViewer>
</Expander.Content>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>

Categories