I have an issue with DataTemplates en ContentControl. My case is very specific.
XAML page:
<Page
x:Class="Questionnaires.QuestionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Questionnaires"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:selectors="using:Questionnaires.TemplateSelectors"
xmlns:interop="using:Windows.UI.Xaml.Interop"
mc:Ignorable="d">
<Page.Resources>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<selectors:QuestionTypeItemTemplateSelector x:Key="QuestionTypeSelector" />
<selectors:AnswerTypeItemTemplateSelector x:Key="AnswerTypeSelector"/>
<DataTemplate x:Key="SingleSelectQuestionItemTemplate">
<Grid Margin="10">
<RadioButton HorizontalAlignment="Left" VerticalAlignment="Center"
IsChecked="{Binding IsChecked, Mode=TwoWay}"
Width="600" Height="Auto" GroupName="groupName">
<RadioButton.Content>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap"/>
</RadioButton.Content>
</RadioButton>
</Grid>
</DataTemplate>
<DataTemplate x:Key="FreeQuestionItemTemplate">
<Grid Margin="10">
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource AnswerTypeSelector}" />
<!--
<GridView ItemsSource="{Binding}" SelectionMode="None">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
-->
</Grid>
</DataTemplate>
<DataTemplate x:Key="MultiSelectQuestionItemTemplate">
<Grid Margin="10">
<CheckBox HorizontalAlignment="Left" VerticalAlignment="Center"
IsChecked="{Binding IsChecked, Mode=TwoWay}" Width="600">
<CheckBox.Content>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap"/>
</CheckBox.Content>
</CheckBox>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LabelAnswerItemTemplate">
</DataTemplate>
<DataTemplate x:Key="TextAreaAnswerItemTemplate">
</DataTemplate>
<DataTemplate x:Key="TextFieldAnswerItemTemplate">
</DataTemplate>
<DataTemplate x:Key="DateAnswerItemTemplate">
</DataTemplate>
<DataTemplate x:Key="SliderAnswerItemTemplate">
<Grid Margin="10">
<Slider Width="600" Minimum="0" Maximum="100" Value="25" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<Grid.Background>
<ImageBrush Stretch="None" ImageSource="Assets/IS_Bol_White.png"/>
</Grid.Background>
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="108*"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="235*"/>
<ColumnDefinition Width="1011*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="pageTitle" Text="{Binding Path=Assignment.Definition.Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40" Grid.ColumnSpan="2" FontSize="48"/>
<Image Grid.Column="2" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,30,0" Width="252" Height="71" Source="ms-appx:///Assets\innovationstudio.png" />
<Grid Grid.Column="2" Grid.Row="1" Margin="3,0,358,0" Width="650">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ProgressBar Grid.Row ="0" Maximum="1" Value="{Binding Progress}" IsIndeterminate="False" Grid.ColumnSpan="2" Foreground="Black"/>
<TextBlock Grid.Row="1" Grid.ColumnSpan="2" Margin="10 20" TextAlignment="Left" HorizontalAlignment="Left" Style="{StaticResource SubheaderTextBlockStyle}"
Text="{Binding CurrentQuestion.Text}" />
</Grid>
<GridView Grid.Column="2" Grid.Row="2" ItemsSource="{Binding CurrentQuestion.PossibleAnswers}"
ItemTemplateSelector="{StaticResource QuestionTypeSelector}" SelectionMode="None">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
<Grid Grid.Column="2" Grid.Row="3" Margin="3,0,358,0" Width="650">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btn_Previous" Grid.Column="0" HorizontalAlignment="Left" Content="Vorige" Height="59" Width="175" IsEnabled="{Binding IsPreviousButtonEnabled}" Click="btnPrevious_Click"/>
<Button x:Name="btn_Next" Grid.Column="1" HorizontalAlignment="Right" Content="Volgende" Height="59" Width="175" IsEnabled="{Binding IsNextButtonEnabled}" Click="btnNext_Click"/>
</Grid>
</Grid>
</Page>
I use an ItemTemplateSelector to specify which type of Question it's going to be. The QuestionType is definded in the PossibleAnswer object. My ItemTemplateSelector looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Questionnaires.Models;
using Questionnaires.ViewModels;
namespace Questionnaires.TemplateSelectors
{
public class QuestionTypeItemTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
switch (((PossibleAnswer)(item)).QuestionType)
{
case "FREE":
return
((Page) ((Frame) Window.Current.Content).Content).Resources["FreeQuestionItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "SINGLE_SELECT":
return
((Page) ((Frame) Window.Current.Content).Content).Resources["SingleSelectQuestionItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "MULTI_SELECT":
return
((Page) ((Frame) Window.Current.Content).Content).Resources["MultiSelectQuestionItemTemplate"]
as Windows.UI.Xaml.DataTemplate;
case "DROPDOWN":
return
((Page) ((Frame) Window.Current.Content).Content).Resources["DropdownQuestionItemTemplate"]
as Windows.UI.Xaml.DataTemplate;
default:
return null;
}
}
}
}
This way I specify which datatemplate needs to be shown on my page. I'm currently working on the FREE questions, so i'm talking specifically about one template now. The template on my xaml looks like this:
<Page.Resources>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<selectors:QuestionTypeItemTemplateSelector x:Key="QuestionTypeSelector" />
<selectors:AnswerTypeItemTemplateSelector x:Key="AnswerTypeSelector"/>
<DataTemplate x:Key="FreeQuestionItemTemplate">
<Grid Margin="10">
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource AnswerTypeSelector}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="SliderAnswerItemTemplate">
<Grid Margin="10">
<Slider Width="600" Minimum="0" Maximum="100" Value="25" />
</Grid>
</DataTemplate>
</Page.Resources>
To make things a little clearer: there is a difference between QuestionType and PossibleAnswerType.
QuestionType can be :
FREE
SINGLE_SELECT
MULTI_SELECT
DROPDOWN
TABLE
PossibleAnswerType can be :
LABEL
TEXT_AREA
TEXT_FIELD
DATE
SLIDER
I try to get the PossibleAnswerType of my PossibleAnswer in the FreeQuestionTemplate.
I'm using the ContentControl to do this, but the binding of my PossibleAnswer doesn't seem to work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Questionnaires.Models;
namespace Questionnaires.TemplateSelectors
{
public class AnswerTypeItemTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
switch (((PossibleAnswer) (item)).PossibleAnswerType)
{
case "LABEL":
return
((Page)((Frame)Window.Current.Content).Content).Resources["LabelAnswerItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "TEXT_AREA":
return
((Page)((Frame)Window.Current.Content).Content).Resources["TextAreaAnswerItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "TEXT_FIELD":
return
((Page)((Frame)Window.Current.Content).Content).Resources["TextFieldAnswerItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "DATE":
return
((Page)((Frame)Window.Current.Content).Content).Resources["DateAnswerItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
case "SLIDER":
return
((Page)((Frame)Window.Current.Content).Content).Resources["SliderAnswerItemTemplate"]
as
Windows.UI.Xaml.DataTemplate;
default:
return null;
}
}
}
}
In my AnswerTypeItemTemplateSelector, the item object is always null. Anyone got me some suggestions on how to do this?
Kind regards!
Ok, looking over your new code, I think that I've worked out what your problem is. Your AnswerTypeItemTemplateSelector is used in your FreeQuestionItemTemplate DataTemplate, which is used in your QuestionTypeItemTemplateSelector. Unless you've left out some XAML, it seems as though you aren't using your QuestionTypeItemTemplateSelector anywhere, so none of this is 'plugged in'.
UPDATE >>>
In order for any Binding to work, you must set the DataContext of your Page to some meaningful value. The DataContext tells the elements in the UI where to look for its data bound values. Without setting a DataContext, the UI elements will have no access to any data (unless some has been declared in XAML, but let's not confuse matters with this). Please take a look at the DataContext in WPF article on CodeProject for more information.
Related
Currently I am implementing an app using HamburgerControlMenu from Mahapps.Metro toolkit.
I need to focus a specific HambugerMenu Item by code, after an event.
This is the WPF code:
<Grid.Resources>
<DataTemplate x:Name="aa" x:Key="MenuItemTemplate" DataType="{x:Type viewModels:MenuItem}">
<Grid x:Name="gridMain" Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
Focusable="False"
Content="{Binding Icon}"/>
<TextBlock x:Name="txtBlockMenu"
Grid.Column="1"
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Text}" />
</Grid>
</DataTemplate>
</Grid.Resources>
<controls:HamburgerMenu x:Name="HamburgerMenuControl"
Foreground="White"
PaneBackground="#FF444444"
IsPaneOpen="False"
ItemsSource="{Binding Menu}"
OptionsItemsSource="{Binding OptionsMenu}"
ItemClick="HamburgerMenuControl_OnItemClick"
OptionsItemClick="HamburgerMenuControl_OnItemClick"
ItemTemplate="{StaticResource MenuItemTemplate}"
OptionsItemTemplate="{StaticResource MenuItemTemplate}"/>
Little help would be great.
Set the SelectedIndex or SelectedItem property. The following will for example select the second item at index 1:
HamburgerMenuControl.IsPaneOpen = true;
HamburgerMenuControl.SelectedIndex = 1;
you can set it using :
this.*yourHamburgerControlName*.SelectedIndex = *InsertHere the position of your HamburgerMenuItem in the ItemSource*;
I am currently in the process of making a 'Preferences' window in my C# WPF program.
The aim of this window is to have a ListView on the left, and a list of tweakable controls on the right.
Each item in the ListView directly corresponds to a Grid that contains all of the controls under the selected item's content.
Once the item in the ListView is changed, the current grid's visibility must be collapsed, and the grid that corresponds to the item selected's visibility must be changed to visible.
I thought that DataBinding might work for this, however I have no idea how to use it. Could someone please inform me how to implement this feature?
I have only one grid at the moment. The whole window looks like this:
<Window x:Class="DarkOrbit_Skill_Price_Calculator.DarkOrbit_Skill_Price_Calculator___Preferences"
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:DarkOrbit_Skill_Price_Calculator"
mc:Ignorable="d"
Title="DarkOrbit Skill Price Calculator - Preferences" Height="360" Width="640" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListView Name="ListView_PreferenceOption" Width="150" Margin="5" SelectionChanged="SelectionChanged_ListView_PreferenceOption">
<ListViewItem IsSelected="True">
<StackPanel Orientation="Horizontal">
<Image Source="Images\Installing Updates.png" Height="35"/>
<TextBlock Text="Update" FontSize="14" FontFamily="Segoe UI" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
</ListViewItem>
</ListView>
<Grid Margin="5" Name="Grid_Update" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Update Version Architecture" VerticalAlignment="Center"/>
<ComboBox IsReadOnly="True" Width="100" Margin="5">
<ComboBoxItem Content="64-Bit"/>
<ComboBoxItem Content="32-Bit" IsSelected="True"/>
</ComboBox>
</StackPanel>
</Grid>
</Grid>
</Window>
I have absolutely no clue as to how to swap the grid depending on the index selected.
You can bind the visibility of each grid to the selected state of its corresponding list item by referencing the ListViewItem element. Something like this:
<Grid>
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="Converter" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListView Width="150" Margin="5">
<ListViewItem IsSelected="True" x:Name="One">
<TextBlock Text="Update" FontSize="14" FontFamily="Segoe UI"
VerticalAlignment="Center" Margin="5"/>
</ListViewItem>
<ListViewItem IsSelected="False" x:Name="Two">
<TextBlock Text="Foo" FontSize="14" FontFamily="Segoe UI"
VerticalAlignment="Center" Margin="5"/>
</ListViewItem>
</ListView>
<Grid Margin="5" Grid.Column="1"
Visibility="{Binding IsSelected, ElementName=One, Converter={StaticResource Converter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Update Version Architecture" VerticalAlignment="Center"/>
<ComboBox IsReadOnly="True" Width="100" Margin="5">
<ComboBoxItem Content="64-Bit"/>
<ComboBoxItem Content="32-Bit" IsSelected="True"/>
</ComboBox>
</StackPanel>
</Grid>
<Grid Margin="5" Grid.Column="1"
Visibility="{Binding IsSelected, ElementName=Two, Converter={StaticResource Converter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Update Something Else" VerticalAlignment="Center"/>
<ComboBox IsReadOnly="True" Width="100" Margin="5">
<ComboBoxItem Content="64-Bit"/>
<ComboBoxItem Content="32-Bit" IsSelected="True"/>
</ComboBox>
</StackPanel>
</Grid>
</Grid>
For those who are having the same predicament and want to use C# code to make this work, I eventually thought of the following code:
StackPanel[] allGrids = { Grid_1, Grid_2, Grid_3, Grid_4, ... }; //Replace StackPanel with the
//type of control you are using, e.g. Grid or WrapPanel.
foreach (StackPanel grid in allGrids)
{
grid.Visibility = Visibility.Collapsed; //collapse all grids
}
allGrids[(your listview/other control).SelectedIndex].Visibility = Visibility.Visible;
//make the grid you need visible
I am writing a WPF client and have created a custom Chat control that will be used within the client, the Chat control comprises of a ChatClient that handles joining and leaving the Chat service and displaying a list of connected Users as per the following XAML:
<Style TargetType="{x:Type chat:ChatClient}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type chat:ChatClient}">
<Grid Margin="0,0,0,0" Background="{StaticResource ChatClientBackgroundBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="135" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,0" Background="{StaticResource ChatClientBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="32" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Grid.Row="0" Height="100" Margin="0,0,0,0" Padding="1,1,1,0" BorderBrush="{StaticResource ChatClientAvatarBorderBrush}">
<Image Height="80" Width="80" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
<Image.Clip>
<EllipseGeometry Center="40,40" RadiusX="40" RadiusY="40" />
</Image.Clip>
</Image>
</Border>
<StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
<Ellipse Height="8" Width="8" Fill="{StaticResource ChatClientPresenceOnlineBrush}" Margin="6,-8,0,0" />
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CurrentPerson.Name}" Margin="8,0" Foreground="{StaticResource ChatClientTextBrush}"
FontSize="16" />
</StackPanel>
</Grid>
<Border Grid.Row="1" BorderThickness="0,1,0,0" BorderBrush="{StaticResource ChatClientBorderBrush}">
<Grid Background="{StaticResource ChatClientBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="100" />
</Grid.RowDefinitions>
<ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl>
<Border Style="{StaticResource IsMouseOver}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0"
BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
<Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
<Image.Clip>
<EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
</Image.Clip>
</Image>
</Border>
<TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold"
Text="{Binding Name}"></TextBlock>
</Grid>
</Border>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This is defined in a ResourceDictionary in the Chat assembly and the ChatClient is added as a control to the main application window.
This is all great and when I run the application it connects to the chat server and I get a nice panel to the right of the main window with a list of connected users.
Ok, so my question is specifically related to the following part from the XAML above:
<ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl>
<Border Style="{StaticResource IsMouseOver}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0" BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
<Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
<Image.Clip>
<EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
</Image.Clip>
</Image>
</Border>
<TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold" Text="{Binding Name}"></TextBlock>
</Grid>
</Border>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
In the above DataTemplate an item is created for each connected Person, I would like to know how I can handle the MouseDoubleClick event of the ContentControl from the ChatClient, so that the ChatClient will be responsible for creating the ChatWindow, examples would be good as still quite new to WPF.
I have been reading up on Attached Behaviors but struggling to understand how these would fit in to what I am looking to achieve which is that my ChatClient class has an event handler that is fired when I double click any item added within the DataTemplate.
Any suggestions on how to achieve this will be greatly received.
I recommend you to fire a Command on MouseDoubleClick event.
To connect a MouseDoubleClick event to a Command and pass ClientId to it, you can use somethings like this:
<ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl>
<!-- ــــInputBinding For Mouse LeftDoubleClickــــ -->
<ContentControl.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ClientDoubleClickCommand}"
CommandParameter="{Binding ClientId}"/>
<ContentControl.InputBindings>
<!-- ــــــــــــــــــــــــــــــــــــــــ -->
<Border Style="{StaticResource IsMouseOver}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0" BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
<Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
<Image.Clip>
<EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
</Image.Clip>
</Image>
</Border>
<TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold" Text="{Binding Name}"></TextBlock>
</Grid>
</Border>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
Then you can simply define ClientDoubleClickCommand command in ClientChat class (like other members of it such as People):
public class ChatClient: INotifyPropertyChanged
{
//-------- Peopole property --------
.
.
.
//-------- ClientDoubleClickCommand --------
ICommand clientDoubleClickCommand;
public ICommand ClientDoubleClickCommand
{
get
{
return clientDoubleClickCommand ??
(clientDoubleClickCommand = new MyCommand(DoThisOnDoubleClick, true));
}
}
private void DoThisOnDoubleClick(object clientId)
{
// Write your target codes (on Mouse Left Double Click) here:
throw new NotImplementedException();
}
//-------- OTHER PROPERTIES AND CODES OF CLASS--------
.
.
.
}
// MyCommand Class: This class is a technique to implement commands easily
public class MyCommand: ICommand
{
private readonly Action<object> _action;
private readonly bool _canExecute;
public MyCommand(Action<object> action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action(parameter);
}
}
public class People: INotifyPropertyChanged
{
// ClientId Property:
.
.
.
// ClientName Property:
.
.
.
//-------- OTHER PROPERTIES AND CODES OF CLASS--------
.
.
.
}
In this example, i assumed you have a ClientId property in your People class to keep id of each client.
Now you have a People property, it is a list of clients and you used it like this:
<ItemsControl ItemsSource="{Binding Path=People,........
On the other hand if the ItemsControl DataContext be »» ChatClient class
then we have access to ClientDoubleClickCommand in it and access to ClientId in People class (by ItemsSource) in the following line inside ItemsControl block:
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ClientDoubleClickCommand}"
CommandParameter="{Binding ClientId}"/>
I have a .NET 4.0 WPF application using the MVVM pattern and I've been unable to achieve the desired outcome on one of the screens (UserControl as View). I have stripped down most of the page to show the core of the problem. The page consists of a grid with three rows and one column. The first row contains header text and the last row contains a Save button. The middle row contains a grid with one row and column and displays an ObservableCollection in an ItemsControl with a data template of a custom user control. There are ten items in the collection and I want them to display in two columns and five rows so I have a WrapPanel as an ItemsPanelTemplate.
I want the ItemsControl to scroll within the available space but it is expanding to the size of content and most of it is being cropped off the bottom of the page.
I am listing the XAML for user control the ObservableCollection uses as a data template and the XAML for the main page below that. Any help is greatly appreciated.
<UserControl x:Class="OIL.UserControls.ShopNotes.ShopNoteComponent"
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="120" d:DesignWidth="150">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" Width="140" Margin="5,5,5,5" HorizontalAlignment="Center" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" CornerRadius="5">
<StackPanel Width="120" Margin="0,5,0,5" HorizontalAlignment="Center" VerticalAlignment="Top" Orientation="Vertical">
<Image Height="25" Width="30" HorizontalAlignment="Left" Source="/OIL;component/Images/BlueCam.png">
<Image.ToolTip>
<Image Source="{Binding Path=ToolTipImagePath}" />
</Image.ToolTip>
</Image>
<Label Style="{DynamicResource LargeText}" Content="{Binding Path=ComponentTitle}" />
<CheckBox Width="80" Margin="0,5,0,5" HorizontalAlignment="Left" Style="{DynamicResource NormalText}" Content=" Mandatory?"
IsChecked="{Binding Path=ComponentMandatory, Mode=TwoWay}"
IsEnabled="{Binding Path=ComponentSelected}" />
<CheckBox Width="15" Margin="0,5,0,5" HorizontalAlignment="Center"
IsChecked="{Binding Path=ComponentSelected, Mode=TwoWay}" />
</StackPanel>
</Border>
</Grid>
And here is the main XAML page:
<UserControl x:Class="OIL.View.ConfiguratorViews.Configurator_ShopNotes_Tab"
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:igWPF="http://infragistics.com/Editors"
xmlns:uc="clr-namespace:OIL.UserControls.ShopNotes"
mc:Ignorable="d"
d:DesignHeight="570" d:DesignWidth="866">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<DataTemplate x:Key="ShopNotesComponentsTemplate">
<uc:ShopNoteComponent />
</DataTemplate>
</UserControl.Resources>
<Border Margin="10" CornerRadius="13" BorderThickness="3" BorderBrush="#FF666666">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal">
<Button Height="30" Width="75" Margin="10,5,0,5" HorizontalAlignment="Center" VerticalAlignment="Center" Background="{x:Null}"
Command="{Binding Path=AddNewTemplateCommand}"
Content="Add" />
<Button Height="30" Width="75" Margin="10,5,0,5" HorizontalAlignment="Center" VerticalAlignment="Center" Background="{x:Null}"
Command="{Binding Path=EditTemplateCommand}"
Content="Edit" />
<Grid Margin="10,5,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding Path=IsNewTemplate, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBox Height="30" Width="250" HorizontalAlignment="Left" VerticalAlignment="Center" Style="{DynamicResource NormalText}" Text="{Binding Path=TemplateDescription}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding Path=IsEditedTemplate, Converter={StaticResource BooleanToVisibilityConverter}}">
<igWPF:XamComboEditor Name="cmbShopNotesTemplate" Height="30" HorizontalAlignment="Left" VerticalAlignment="Center"
ItemsSource="{Binding Path=ShopNoteTemplates, Mode=TwoWay}"
DisplayMemberPath="CONFIGURATION_DESC"
SelectedItem="{Binding Path=SelectedShopNoteTemplate, ValidatesOnDataErrors=True}"
Value="Select Shop Notes Template"
NullText="Select Shop Notes Template"
IsEditable="True">
</igWPF:XamComboEditor>
</StackPanel>
</Grid>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Height="30" Margin="0,5,0,5" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{DynamicResource NormalText}" Content="* Hover over camera icon to view Shop Note component" />
<ItemsControl Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left"
ItemsSource="{Binding Path=ShopNoteComponents, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemTemplate="{StaticResource ShopNotesComponentsTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="300" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
<Button Grid.Row="2" Grid.Column="0" Height="30" Width="150" Margin="10,10,0,10" HorizontalAlignment="Left" VerticalAlignment="Center"
Background="{x:Null}"
Command="{Binding Path=SaveTemplateCommand}"
Content="Save" />
</Grid>
</Border>
EDIT: Changed question title as I have removed the ScrollViewer between starting the question and actually posting it. Also, noticed the Save button was in the inner grid rather than outer grid so I have corrected that (no change in rendering).
An ItemsControl does not have its own ScrollViewer like a ListBox. You can either replace you ItemsControl with a ListBox, or simply wrap it in a ScrollViwer, being careful to move the Grid.Row and Grid.Column settings like this:
<ScrollViewer Grid.Row="1" Grid.Column="0">
<ItemsControl HorizontalAlignment="Left" ItemsSource="{Binding Path=Items,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemTemplate="{StaticResource ShopNotesComponentsTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="300" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
Hi I see there have been many questions about ListBox and filling the entire space for the DataTemplate but I still cannot get anything to work. What I have is a ListBox and the DataTemplate has a UserControl. How do I get my UserControl to stretch the data to fill the space?
MainWindow XAML snippet:
<ListBox x:Name="ConfiguredItemsList">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ConfiguredItem DataContext="{Binding}" HorizontalContentAlignment="Stretch" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
UserControl XAML snippet:
<UserControl.Resources>
<local:ImagePathConverter x:Key="ImagePathConverter"/>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" x:Name="NameLabel" Text="Name:" />
<TextBlock Grid.Row="0" Grid.Column="1" x:Name="tbName" Text="{Binding Path=Name}" />
<TextBlock Grid.Row="1" Grid.Column="0" x:Name="DescriptionLabel" Text="Description: " />
<TextBlock Grid.Row="1" Grid.Column="1" x:Name="Description" Text="{Binding Path=Description}" />
<TextBlock Grid.Row="2" Grid.Column="0" x:Name="TimeLabel" Text="Time:" />
<TextBlock Grid.Row="2" Grid.Column="1" x:Name="Time" Text="{Binding Path=ChangeTime, StringFormat={}{0:h:mm tt}}" />
</Grid>
<Border Grid.Column="1" BorderThickness="1" BorderBrush="Black">
<Image Source="{Binding Path=WallpaperInfo, Converter={StaticResource ImagePathConverter}}" />
</Border>
</Grid>
Have you tried to set HorizontalContentAlignment to stretch on list box level?
<ListBox x:Name="ConfiguredItemsList" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ConfiguredItem DataContext="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: I have set HorizontalContentAlignment property of ListBox instead of Item.