s:ScatterView ItemTemplate - how to set height or width? - wpf

I have a small problem while working on software for a Surface: I have a binded ScatterView and its items have a DataTemplate. My question is : how do I set the width and height of the ScatterViewItem that it is created from the ItemTemplate?
<s:ScatterView Name="svMain" Loaded="svMain_Loaded" ItemsSource="{Binding BallsCollection}" >
<s:ScatterView.ItemTemplate >
<DataTemplate>
<DockPanel LastChildFill="True" >
<DockPanel.Background>
<ImageBrush ImageSource="image\note.png" Stretch="Fill" />
</DockPanel.Background>
<TextBox Background="Transparent" DockPanel.Dock="Top" Text="{Binding Path=Message}"
IsReadOnly="True" TextWrapping="Wrap"></TextBox>
</DockPanel>
</DataTemplate>
</s:ScatterView.ItemTemplate>
</s:ScatterView>

I believe you can set that through the ItemContainerStyle, like with other ItemsControls, but i'm not certain, as i do not have the Surface SDK.
<s:ScatterView.ItemContainerStyle>
<Style TargetType="{x:Type s:ScatterViewItem}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
</Style>
</s:ScatterView.ItemContainerStyle>
You can of course also use bindings instead fixed units.

Related

Excess border selection in WPF's Lisbox [duplicate]

I have a ListBox in which each item is a StackPanel. The StackPanel consist of an Image and a TextBlock below it:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Path=ImageFilePath}"/>
</Image.Source>
</Image>
<TextBlock Text="Title" TextAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
It looks like this:
When the user select an item, I get the default blue rectangle that surround the StackPanel:
Now, I want to make a different border for the selected-item, but I want it to surround only the image.
I know how to make a control template and put a custom border around the ContentPresenter, but this, of course, will surround the whole StackPanel, not only the Image.
I don’t know if making changes to the ContentPresenter is possible, and if it is a good idea at all. If there is other way to achieve the look I want, it will be fine as well.
Right, the ListBox's own ContentPresenter isn't helpful for what you're doing. You want to a) eliminate the ListBox's own selection visuals and b) replace them with something more suitable in the DataTemplate for your items.
The default selection visual is applied by the default template for ListBoxItem. So replace that template. Using a Style in the resources for your ListBox, apply your own control template to ListBoxItem. Not much to it, just present the content and don't provide a selection background. Then you handle the selection visuals with a trigger in your data template, where your image and your label are defined and you can apply changes to one and not the other. The below example works for me.
Note that there's some fiddling with the HorizontalAlignment on the Border element to make it cling to the Image element within it. Also, I wrote a quickie test viewmodel whose Items property is called Items; I assume this is not the name of the collection member you're using to populate your own ListBox.
<ListBox
Margin="8"
ItemsSource="{Binding Items}"
>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Border
x:Name="HighlightBorder"
BorderThickness="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"
>
<Border.Style>
<Style TargetType="Border">
<!-- MUST set default BorderBrush via a style, if you set it at all.
As an attribute on the Border tag, it would override the effects of
the trigger below.
-->
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Border.Style>
<Image Source="{Binding ImageFilePath}" />
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter TargetName="HighlightBorder" Property="BorderBrush" Value="Orange" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

WPF: Simple MSWord-like color picker button

Is there a quick and easy way to implement a color picker button like the one in MS Word?
I want the user to choose from a number of predefined colors in a dropdown. The selected color should be displayed when the button is closed. When the user clicks the button, an event or command should be triggered. I want to use one button instance to set the text color in a RichTextBox, and another one to set the background color (similar to MS Word).
My first approach was to use a ComboBox with a DataTemplate which contains a button.
This does not work: The button's command is not triggered when the user clicks it. Instead, the dropdown of the ComboBox opens. I don't know the exact reason, but maybe the IsHitTestVisible=false attributes in the ComboBox default template? See: http://msdn.microsoft.com/en-us/library/dd334408%28v=vs.95%29.aspx
<UserControl x:Class="MyBrushPicker"
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"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Height="Auto" Width="Auto" MinWidth="50">
<UserControl.Resources>
<!--
Provide two different DataTemplates:
- SelectionBoxTemplate is used to display the selected color when the ComboBox is closed.
It contains a button which should be clickable (does not work).
- NormalItemTemplate is used to display a color in the opened ComboBox popup.
See:
http://stackoverflow.com/questions/2214696/wpf-how-to-customize-selectionboxitem-in-combobox
-->
<DataTemplate x:Key="NormalItemTemplate">
<Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate">
<!-- This button cannot be clicked: PreviewMouseDown and Button_Click events are never triggered. -->
<Button Click="Button_Click" PreviewMouseDown="Button_PreviewMouseDown">
<Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
</Button>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</UserControl.Resources>
<ComboBox IsReadOnly="True" IsEditable="False"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectableBrushes, Mode=OneWay}"
SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedBrush, Mode=TwoWay}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
MinHeight="50"
MaxDropDownHeight="200"
ItemTemplate="{StaticResource CombinedTemplate}"
>
<ComboBox.Resources>
<Style TargetType="ComboBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="200" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ComboBoxItem">
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
</Style>
</ComboBox.Resources>
</ComboBox>
</UserControl>
Is there a way to make the button work correctly?
Are there any better approaches?
EDIT: Using the Snoop tool revealed that the IsHitTestVisible attribute of the unnamed ContentPresenter inside the ComboBox is actually set to false (ValueSource: ParentTemplate). If I set this property to true using Snoop, the button becomes clickable.
Can I change this property from a style?
At least, the following doesn't work:
<ComboBox.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="IsHitTestVisible" Value="True" />
</Style>
</ComboBox.Resources>
Assuming you are not just doing this as a learning exercise (which make using a library pointless)...
Take a look at: Extended WPF Toolkit - Color Picker
I've used it before for simple a plug-and-play WPF color-picker and it should solve your problem nicely.

Set a Usercontrol as a Datatemplate

I have the following ProductList template snipet
<Style x:Key="ProductListStyle" TargetType="{x:Type s:SurfaceListBox }">
<Setter Property="Background" Value="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemBackgroundBrushKey}}" />
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="Height" Value="234" />
<Setter Property="ItemTemplateSelector">
<Setter.Value>
<sc:ProductListTemplateSelector>
<sc:ProductListTemplateSelector.NormalItemTemplate>
<DataTemplate>
<StackPanel RenderTransformOrigin="0.5, 0.5"
Margin="7,0,0,0"
MinWidth="171" MaxWidth="171"
MinHeight="235" MaxHeight="235">
<Image Margin="14,21,21,11" Source="{Binding XPath=#Image}"
Height="149" Width="101" />
<TextBlock Text="{Binding XPath=#Name}"
MaxWidth="116"
FontSize="12"
Margin="21,0,21,21"
FontFamily="Segoe360"
TextAlignment="Center"
TextWrapping="Wrap"
Foreground="{DynamicResource {x:Static s:SurfaceColors.ListBoxItemForegroundBrushKey}}"
HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</sc:ProductListTemplateSelector.NormalItemTemplate>
I need to replace the DataTemplate of this style to be set using my user control like
<local:MyUserControl>
By keeping only between section I did not get my control displayed when my Itemsource is set with a collection of myUserControl
Usually I just add the DataTemplate in the Resources. This can be <Window.Resources> or <App.Resources> if the data template is global, or FrameworkElement.Resources if the template should only be applied in a specified scope. For example, adding the template to ListView.Resources would only apply the template within a specific ListView.
<Window.Resources>
<DataTemplate DataType="{x:Type local:ProductModel}">
<local:MyUserControl />
</DataTemplate>
</Window.Resources>
As a side note, your original question leads me to believe that you are binding a ListView to a collection of MyUserControl objects. I really wouldn't recommend this, but if this is the case you can use a ContentControl in your DataTemplate with it's Content bound to your object, and it should display correctly.
<ContentControl Content="{Binding }" />

Binding the background colour of a control using a trigger in WPF/XAML

Okay, first off I have no experience of WPF whatsoever so please bear with me and apologies if my terminology is a little wayward... ;)
The following code snippet is part of a WPF application that I have inherited. The trigger governs whether mandatory fields on a particular form are highlighted or not. The code works but the highlighting seems to apply to the control and the border (??) which contains it.
<ItemsControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="clr-namespace:Caliburn.PresentationFramework.ApplicationModel;assembly=Caliburn.PresentationFramework"
x:Class="company.product.Jobs.JobParametersEditor"
IsTabStop="False">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel MinHeight="30">
<TextBlock Text="{Binding DisplayName, Mode=OneWay}"
DockPanel.Dock="Left"
VerticalAlignment="Center"
MinWidth="120"
Margin="6,0" />
<Border>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background"
Value="{x:Null}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}"
Value="False">
<Setter Property="Background"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentControl cal:View.Model="{Binding ValueEditor}"
ToolTip="{Binding ToolTip}"
IsTabStop="False"
MinHeight="19"
VerticalAlignment="Center"
HorizontalAlignment="Stretch" />
</Border>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The result is a bit clunky so I would like to restrict the highlighting to the control only but I can't figure out how to do it. I've tried moving the trigger so that it applies to the ContentControl instead of the Border but that didn't work and fiddling about with border margins, padding and thickness hasn't had any effect either.
Could anybody enlighten me as to how to accomplish this?

How can I use a custom TabItem control when databinding a TabControl in WPF?

I have a custom control that is derived from TabItem, and I want to databind that custom TabItem to a stock TabControl. I would rather avoid creating a new TabControl just for this rare case.
This is what I have and I'm not having any luck getting the correct control to be loaded. In this case I want to use my ClosableTabItem control instead of the stock TabItem control.
<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True"
Controls:ClosableTabItem.TabClose="TabClosed" >
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type Controls:ClosableTabItem}" >
<TextBlock Text="{Binding Path=Id}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type Entities:Case}">
<CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
EDIT: This is what I ended up with, rather than trying to bind a custom control.
The "CloseCommand" im getting from a previous question.
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border
Name="Border"
Background="LightGray"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="25,0,0,0"
SnapsToDevicePixels="True">
<StackPanel Orientation="Horizontal">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="20,1,5,1"/>
<Button
Command="{Binding Path=CloseCommand}"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
Margin="1,1,5,1"
Background="Transparent"
BorderThickness="0">
<Image Source="/Russound.Windows;component/Resources/Delete.png" Height="10" />
</Button>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
<Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
<Setter TargetName="Border" Property="BorderBrush" Value="DarkBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
found a way,
derive a class from TabControl and override this function, in my case I want the items of the tab control (when bound) to be CloseableTabItems
public class CloseableTabControl : TabControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new CloseableTabItem();
}
}
HTH Someone
Sam
You don't want to set the DataType of the DataTemplate in this case. The value of the ItemTemplate property is used whenever a new item needs to be added, and in the case of a tab control it will be used to create a new TabItem. You should declare an instance of your class within the DataTemplate itself:
<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True" Controls:ClosableTabItem.TabClose="TabClosed">
<TabControl.ItemTemplate>
<DataTemplate>
<Controls:ClosableTabItem>
<TextBlock Text="{Binding Path=Id}" />
</Controls:ClosableTabItem>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type Entities:Case}">
<CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
This will cause a new ClosableTabItem to be created whenever a new tab is added to the TabControl.
Update; From your comment, it sounds like that the ItemTemplate controls what is created within the TabItem, rather than changing the TabItem itself. To do what you want to do, but for a TreeView, you would set the HeaderTemplate. Unfortunately, I don't see a HeaderTemplate property of TabControl.
I did some searching, and this tutorial modifies the contents of the tab headers by adding controls to TabItem.Header. Maybe you could create a Style for your TabItems that would add the close button that your class is currently adding?

Resources