Binding the control's property in its DataTemplate - wpf

I have a custom control where I have modified a ListView. I have a DataTemplate which shows each item as an icon of width 128 and a label beneath it.
<DataTemplate x:Key="AeroIconTemplate">
<Grid VerticalAlignment="Top" Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Image}" Width="128"
MaxHeight="128" Margin="0"/>
<TextBlock Grid.Row="1" Text="{Binding Title}" Foreground="Black"
TextWrapping="WrapWithOverflow" Margin="0"
TextTrimming="CharacterEllipsis" Width="128" MaxHeight="60" />
</Grid>
</DataTemplate>
Now I have added a property to the ListView itself called IconSize. This takes an integer between 16 and 256.
I want to bind the Width, MaxHeight of the Image and the Width of the TextBlock to this property. So whenever the IconSize property is changed the template is adjusted in size. As you can see I am currently binding some stuff to the data object (the image source and the label text), but in this case I want to bind to the ListView control.
How do I do this?
Thanks!

You can use the RelativeSource for that:
... Width="{Binding IconSize,RelativeSource={RelativeSource AncestorType=ListView}}" ...
Be sure to define the correct type, since the WPF ListView does not have the property IconSize. You may need to define your class.

Related

Select a Control alone inside a ListView not the whole ListViewItem

I have a ListView with ItemTemplate contains an Image, TextBox, ComboBox, TextBlock etc when selecting any control should highlight the selected control not the whole ListViewItem any style would be fine.
XAML
<ListView Margin="10" ItemsSource="{Binding TCollection}" SelectedItem="{Binding SelectedTImage}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<Image Width="70" Height="70" HorizontalAlignment="Center">
<Image.Source>
<BitmapImage DecodePixelWidth="300" DecodePixelHeight="300" UriSource="{Binding TImage}"/>
</Image.Source>
</Image>
<TextBox Text="{Binding text}"/>
<TextBlock Text="Contents"/>
<ComboBox/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Any help
What you want is to disable event bubbling. Sure, it hits the control first, but the click event bubbles to the list item, too. In order to stop it, you have to put an event handler on all the controls (button, etc) and set e.Handled = true in the handler to prevent it from going to the ListViewItem.
See: disable event-bubbling c# wpf for more info.
If you never want items to be selected at all (hard to tell with your example), then you'd want to use an ItemsControl instead. That will let you bind to a collection of items and display all of them but it doesn't have the concept of a selected item.

UserControl Expand Vertically when Window is expanded

I'm having trouble getting my UserControl to expand vertically when my window is expanded.
My UserControl currently sits inside a ItemsControl which is stretching correctly by setting the VerticalAlignment="Stretch" property on the ItemsControl.
I add the following UserControl to the ItemsControl:
<UserControl MinWidth="930">
<Grid VerticalAlignment="Stretch" Background="Red">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="730*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="400" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DockPanel Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="2" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Pink" LastChildFill="True">
<ItemsControl Name="itemPanelOverview" Grid.Column="1" Background="Black" Margin="0"/>
</DockPanel>
</Grid>
</UserControl>
The UserControl is called in an ItemsControl inside of a TabControl like so:
<TabItem>
<TabItem.Header>
HEADER EG
</TabItem.Header>
<ItemsControl Name="contentItems" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" VerticalAlignment="Stretch" Background="Blue">
<Grid Height="35" Background="{DynamicResource GrayMenuGradient}" >
<Image Source="..." Stretch="None" />
<TextBlock Text="{Binding WelcomeMessage}" />
</Grid>
</ItemsControl>
</TabItem>
It appears that the ItemsControl (contentItems) is stretching as expected, as I can see the blue background stretching correctly.
I haven't set the height for this UserControl anywhere other than the Row Definitions. Is there something I'm missing?
There are at least two aspects at play here:
The first is that when you have items in an ItemsControl, each item is actually inside an ItemContainer, so it is the container that you want to stretch.
You can design the container by declaring an ItemContainerTemplate for your ItemsControl: http://msdn.microsoft.com/en-us/library/system.windows.controls.itemcontainertemplate.aspx
The second consideration is the ItemsPanelTemplate, which determines into what type of panel the items are placed. The ability of the items in the ItemsControl to fill up the available space is going to depend on the type of container as much as on the type of ItemContainer. For example, if you use a StackPanel for the ItemsPanelTemplate, it won't fill up available space because StackPanel grows and shrinks according to its contents. A DockPanel could potentially work, but only the last child would grow to fill available space. Perhaps a UniformGrid could do the trick.

How to change itemTemplate of an item in itemControl at runtime in silverlihgt 4

I have a ItemControl in silverlight 4 with a Canvas as a ItemPanel, the idea is to simulate a canvas area with drag and dop items.
ItemsControl has a ItemTemplate with a image and one button.
The idea is that when the button of itemTemplate Click the itemTemplate change.
Some of my code:
(Items Control)
<ItemsControl ItemsSource="{Binding Devices}"
ItemTemplate="{StaticResource deviceItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
MouseMove="Canvas_MouseMove"
LostMouseCapture="Canvas_LostMouseCapture"></Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
(ItemTemplate)
<DataTemplate x:Key="deviceItemTemplate">
<ContentControl>
<Grid IsHitTestVisible="True" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Image IsHitTestVisible="False" Grid.Row="0" Stretch="UniformToFill"
Width="50" Height="50"
Source="{Binding ImagePath}"/>
<Button Grid.Row="1" Content="{Binding EditarDispositivoCommand.DisplayName}" Command="{Binding EditarDispositivoCommand.Command}"></Button>
</Grid>
<ContentControl.RenderTransform>
<TranslateTransform X="{Binding X, Mode=TwoWay}" Y="{Binding Y, Mode=TwoWay}"></TranslateTransform>
</ContentControl.RenderTransform>
</ContentControl>
</DataTemplate>
I try to get that when a button in a itemTemplate is clicked the template of this item change to other template from resource.
Was that possible or i taking a bad way. Thanks a lot.
You could try using a DataTemplateSelector for Silverlight - it's not built in like WPF, but it can be achieved with some extra code.
Here is a good example from CodeProject:
http://www.codeproject.com/KB/silverlight/SLTemplateSelector.aspx
Just add an element to you view model to specify the template...
I just used the following article to do what you suggested.
I have two item templates defined for a view and can progamatically change the item template at runtime though codebehind
http://weblogs.asp.net/psheriff/archive/2010/08/25/change-templates-dynamically-in-silverlight.aspx
Hope this helps
(Sample also uses a button to change the item template)

Is there any way to programmatically change a Data/ItemTemplate in Silverlight?

I have a Listbox, which is using an ItemTemplate to display an image. I want to be able to change the size of the displayed image in the ItemTemplate. Through databinding I can change the Width, but the only way I can see how to do this is to add a Property (Say, ImageSize) to the class I am binding to and then change every item in the collection to have a new ImageSize. Is there no way to access the property of an item in that Datatemplate?
E.g.
<navigation:Page.Resources>
<DataTemplate x:Key="ListBoxItemTemplate">
<Viewbox Height="100" Width="100">
<Image Source="{Binding Image}"/>
</Viewbox>
</DataTemplate>
</navigation:Page.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource ListBoxItemTemplate}" ItemSource="{Binding Collection}"/>
</Grid>
Is there anyway to set the Width and Height of the viewbox without binding a property to every element in the collection?
You can use element binding to this. Try something like this:
<UserControl.Resources>
<DataTemplate x:Key="ListBoxItemTemplate">
<Viewbox Height="{Binding Value, ElementName=slider1}"
Width="{Binding Value, ElementName=slider1}">
<Image Source="{Binding Image}"/>
</Viewbox>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="205*" />
<RowDefinition Height="95*" />
</Grid.RowDefinitions>
<ListBox ItemTemplate="{StaticResource ListBoxItemTemplate}"
ItemSource="{Binding Collection}"/>
<Slider x:Name="slider1" Value="100" Maximum="250" Grid.Row="1"/>
</Grid>
If you know the sizes to which you'll be resizing, you could define a number of different ItemTemplates and switch bewteen them.

wpf border control to span the width of listboxItem

Im trying to define a dataTemplate for a business object in my wpf application a collection of which is being bound to a ListBox.
<UserControl.Resources>
<DataTemplate x:Key="ResizedItemsDataTemplate" DataType="{x:Type resizer:ResizeMonitorItem}">
<Border x:Name="bdr" BorderBrush="Blue"
BorderThickness="1"
CornerRadius="2"
Width="auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="14"></RowDefinition>
<RowDefinition Height="14"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding SaveAsFileName}"></TextBlock>
<TextBlock Grid.Row="1" Text="{Binding ResizedImageFilePath}"></TextBlock>
</Grid>
</Border>
</DataTemplate>
</UserControl.Resources>
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0">
<Border BorderThickness="0,0,0,5" BorderBrush="DarkGray" >
<ListBox x:Name="ListBoxResizeItems" ItemsSource="{Binding Path=ResizeItems}" BorderThickness="0" ItemTemplate="{DynamicResource ResizedItemsDataTemplate}">
</ListBox>
</Border>
</Grid>
How can I get the border defined with x:Name=bdr to span the full width of each listbox item? At the moment it only spans the with of the textblocks inside it which dont neccessary fill the full width of the listboxitem and also vary for each listboxitem.
This is probably more to do with the ListBoxItems themselves not taking up the full width of the ListBox. Add the HorizontalContentAlignment="Stretch" attribute to your ListBox and see if it stretches the individual items to fill the width.
Worked it out. The trick is to set the HorizontalContentAlignment="Stretch" on your listbox to make its contents stretch the full width rather than fit the contents only.
<ListBox x:Name="ListBoxResizeItems"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Path=ResizeItems}"
BorderThickness="0"
ItemTemplate="{DynamicResource ResizedItemsDataTemplate}" >
</ListBox>
Sorry Matt, just got your answer thorugh as I was typing this post.
HorizontalContentAlignment is a nice, clean solution compared to what I was trying. Thanks!
Here's what ALMOST worked, but sometimes made a dialog box animated itself wider and wider forever:
Width="{Binding ActualWidth,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"

Resources