UWP Exception when binding to ComboBox - xaml

I am getting this exception:
An unhandled win32 exception occurred in AppName.exe
This occurs only when I Bind to a ComboBox
Here's my XAML:
<ContentDialog x:Name="BrowseBySourceDialog"
Grid.Column="1"
PrimaryButtonText="Accept" IsPrimaryButtonEnabled="False"
Opened="BrowseBySourceDialog_Opened">
<StackPanel Background="White">
<Border Background="DarkGreen" MinHeight="40"
MinWidth="300">
<TextBlock Text="Browse: By Source"
VerticalAlignment="Center"
Foreground="White"
TextAlignment="Center"
HorizontalAlignment="Center" />
</Border>
<StackPanel>
<ComboBox x:Name="BrowseBySourceComboBox"
PlaceholderText="Select Source"
Height="40"
Width="300"
ItemsSource="{x:Bind BrowseBySourceList, Mode=OneWay}"
DisplayMemberPath="Source">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:FeaturedResponseItem">
<TextBlock Text="{x:Bind key}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</StackPanel>
</ContentDialog>
This exception only occurs when the following lines are present:
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:FeaturedResponseItem">
<TextBlock Text="{x:Bind key}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
If the remove the above lines, the combobox surely remains empty but the exception doesn't occur. Is the binding wrong?
Source:
ObservableCollection<FeaturedResponseItem> BrowseBySourceList { get; set; } = new ObservableCollection<FeaturedResponseItem>();
Model:
public class FeaturedResponseItem
{
public string key { get; set; }
public string icon { get; set; }
public bool accessible { get; set; }
}

You can delete DisplayMemberPath="Source" or simply just remove the ItemTemplate all together and change DisplayMemberPath="Source" to DisplayMemberPath="Key".

Related

Binding IsSelected on ListViewItem not working for me in UWP application

I'm working with a list of objects that have a Selected property and I'm trying to bind it to the IsSelected property on ListViewItem within a multi-select ListView control in UWP.
I just can't seem to get the binding to work. The checkboxes in the ListView do not render checked if Selected = True and the Set on Selected never gets triggered when checking an item.
SettingsPage.xaml
<Page.Resources>
<DataTemplate x:Key="PreviewColumnTemplate" x:DataType="models:Column">
<TextBlock>
<Run Text="{x:Bind name}"/>
<Run Text=" ("/>
<Run Text="{x:Bind ColumnValidation.column_label}"/>
<Run Text=") "/>
</TextBlock>
</DataTemplate>
<Style x:Key="previewColumnListViewItem" TargetType="ListViewItem">
</Style>
</Page.Resources>
<ListView
x:Name="previewColumnListView"
ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"
ItemTemplate="{StaticResource PreviewColumnTemplate}"
Height="400"
SelectionMode="Multiple"
SelectionChanged="previewColumnListView_SelectionChanged">
<ListView.Resources>
<Style TargetType="ListViewItem" BasedOn="{StaticResource previewColumnListViewItem}">
<Setter Property="IsSelected" Value="{Binding Selected, Mode=TwoWay}"/>
</Style>
</ListView.Resources>
</ListView>
The ViewModel.CurrentDrillHole.Collar object is of type Table and looks like so:
public class Table : BindableBase
{
public string Name { get; set; }
public TableValidation TableValidation { get; set; }
public List<Column> Columns { get; set; }
public List<Row> Rows { get; set; } = new List<Row>();
}
And the Column object looks like so. It is here I want to bind to the Selected property.
public class Column : BindableBase, INotifyPropertyChanged
{
public string name { get; set; }
public ColumnValidation ColumnValidation { get; set; }
public List<RefEntryValue> LookupValues { get; set; } = null;
private bool _selected = false;
public bool Selected {
get => _selected;
set
{
_selected = value;
OnPropertyChanged();
}
}
}
Any ideas of things I can try would be greatly appreciated. Thanks for the help!
When you set SelectionMode="Multiple", ListViewItem uses the default ListViewItemTemplate whose key is "ListViewItemExpanded".
Its style is as follows:
<Style TargetType="ListViewItem" x:Key="ListViewItemExpanded">
......
<ControlTemplate TargetType="ListViewItem">
<Grid x:Name="ContentBorder"
Control.IsTemplateFocusTarget="True"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
RenderTransformOrigin="0.5,0.5">
……
<Border x:Name="MultiSelectSquare"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
BorderThickness="2"
Width="20"
Height="20"
Margin="12,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Visibility="Collapsed">
<Border.Clip>
<RectangleGeometry Rect="0,0,20,20">
<RectangleGeometry.Transform>
<TranslateTransform x:Name="MultiSelectClipTransform" />
</RectangleGeometry.Transform>
</RectangleGeometry>
</Border.Clip>
<Border.RenderTransform>
<TranslateTransform x:Name="MultiSelectCheckBoxTransform" />
</Border.RenderTransform>
<FontIcon x:Name="MultiSelectCheck"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph=""
FontSize="16"
Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
Visibility="Collapsed"
Opacity="0" />
</Border>
<Border x:Name="MultiArrangeOverlayTextBorder"
Opacity="0"
IsHitTestVisible="False"
Margin="12,0,0,0"
MinWidth="20"
Height="20"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Background="{ThemeResource SystemControlBackgroundAccentBrush}"
BorderThickness="2"
BorderBrush="{ThemeResource SystemControlBackgroundChromeWhiteBrush}">
<TextBlock x:Name="MultiArrangeOverlayText"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DragItemsCount}"
Style="{ThemeResource CaptionTextBlockStyle}"
IsHitTestVisible="False"
Opacity="0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
AutomationProperties.AccessibilityView="Raw" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Style>
As you can see, there is no CheckBox in its style, it is composed by Border and FontIcon.
If you want to solve this problem, I suggest that you could add CheckBox to DataTemplate. By doing this, we can bind “Selected’ to the “IsChecked” property of the CheckBox.
Please refer to the following code.
<ListView
x:Name="previewColumnListView"
ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"
Height="400"
SelectionChanged="previewColumnListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:Key="PreviewColumnTemplate" x:DataType="models:Column">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Selected, Mode=TwoWay}"/>
<TextBlock>
<Run Text="{x:Bind name}"/>
<Run Text=" ("/>
<Run Text="{x:Bind ColumnValidation.column_label}"/>
<Run Text=") "/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how it ended up looking in the end. Does this seem clunky to anyone else? It would be nice if the ListView control made it easier to deal with collections and SelectionMode="Multiple".
SettingsPage.xaml
<ListView
x:Name="previewColumnListView"
ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"
Height="400"
SelectionChanged="previewColumnListView_SelectionChanged"
IsItemClickEnabled="True"
ItemClick="previewColumnListView_ItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Column">
<StackPanel Orientation="Horizontal">
<CheckBox Click="previewColumnListView_CheckBox_Click" IsChecked="{Binding Selected, Mode=TwoWay}"/>
<TextBlock>
<Run Text="{x:Bind name}"/>
<Run Text=" ("/>
<Run Text="{x:Bind ColumnValidation.column_label}"/>
<Run Text=") "/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
SettingsPage.xaml.cs
private async void previewColumnListView_CheckBox_Click(object sender, RoutedEventArgs e)
{
// update the list of selected columns
Settings.CollarPreviewFields = ViewModel.CurrentDrillHole.Collar.Columns.Where(x => x.Selected).Select(x => x.name).ToList();
await App.SaveSettings();
}
private void previewColumnListView_ItemClick(object sender, ItemClickEventArgs e)
{
Column selectedColumn = (Column)e.ClickedItem;
selectedColumn.Selected = !selectedColumn.Selected;
// trigger checkbox click event. will update the list and save.
previewColumnListView_CheckBox_Click(null, null);
}

How to make the textblock text centered in a button with image and text if no image is available in WPF

I have a button with the image and textblock.
Buttons are created dynamically based on the values from the database.
Now for a particular value text is present and no image is there I want to show that text in the center of the button (horizontally and vertically), but it is not working.
Please find the xaml below:
<ItemsControl ItemsSource="{Binding CategoriesList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="100" Margin="5" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<Button.Template>
<ControlTemplate>
<Border CornerRadius="10" Background="Maroon">
<StackPanel Orientation="Vertical">
<Image Source="{Binding CategoryImagePath}" Height="50"></Image>
<TextBlock Text="{Binding CategoryName}" Height="20" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</StackPanel>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
If no image is available I want to show only the text on the button but it should be centered.
If there is Image then I make the Image and text both displayed but when the Image is not available the text is getting displayed but it is not in the center It moves to the top portion of the button.
You can use a DataTemplateSelector to select different templates depending on whether you have an image. Such a selector might look like this:
public sealed class ButtonTemplateSelector : DataTemplateSelector
{
/// <summary>
/// Gets or sets the <see cref="DataTemplate"/> to use when we have an image.
/// The value is set in XAML.
/// </summary>
public DataTemplate ImageTemplate { get; set; }
/// <summary>
/// Gets or sets the <see cref="DataTemplate"/> to use when we don't have an image.
/// The value is set in XAML.
/// </summary>
public DataTemplate NoImageTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Category category = item as Category;
if (category != null)
{
return category.CategoryImagePath == null ? NoImageTemplate : ImageTemplate;
}
return base.SelectTemplate(item, container);
}
}
I'm assuming a model object something like this:
public class Category
{
public string CategoryImagePath { get; set; }
public string CategoryName { get; set; }
}
Create and initialize a ButtonTemplateSelector resource in your XAML, then reference it from your ItemsControl:
<Window
x:Class="WPF.MainWindow"
x:Name="self"
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:wpf="clr-namespace:WPF"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<Grid.Resources>
<wpf:ButtonTemplateSelector x:Key="ButtonTemplateSelector">
<wpf:ButtonTemplateSelector.ImageTemplate>
<DataTemplate DataType="wpf:Category">
<Button
Width="100"
Margin="5"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">
<Button.Template>
<ControlTemplate>
<Border CornerRadius="10" Background="Maroon">
<StackPanel Orientation="Vertical">
<Image
Source="{Binding CategoryImagePath}"
Height="50" />
<TextBlock
Foreground="White"
Text="{Binding CategoryName}"
Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</wpf:ButtonTemplateSelector.ImageTemplate>
<wpf:ButtonTemplateSelector.NoImageTemplate>
<DataTemplate DataType="wpf:Category">
<Button
Width="100"
Margin="5"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">
<Button.Template>
<ControlTemplate>
<Border
CornerRadius="10"
Background="Maroon"
Height="70">
<TextBlock
Foreground="White"
Text="{Binding CategoryName}"
Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</wpf:ButtonTemplateSelector.NoImageTemplate>
</wpf:ButtonTemplateSelector>
</Grid.Resources>
<ItemsControl
DataContext="{Binding ElementName=self}"
ItemsSource="{Binding CategoriesList}"
ItemTemplateSelector="{StaticResource ButtonTemplateSelector}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Window>
For completeness, the code-behind for the window:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
public IEnumerable<Category> CategoriesList { get; } = new List<Category>
{
new Category { CategoryName = "First", CategoryImagePath = "/Assets/Square.bmp" },
new Category { CategoryName = "Second", CategoryImagePath = null },
};
}
This shows up as follows, which I think is what you're asking:

XAML Gridview to add an item directly

I successfully coded an XAML Gridview to show list of items.
However, I want to add an [+(ADD ITEM)] button at the end of the Gridview.
The ADD button has should have a custom template (at least a default button) which is different from the content item.
My XAML source is below:
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="116,136,116,46"
ItemsSource="{Binding Source={StaticResource DataSource}}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Subject}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<!--
Something like that..
<Button Content="+" x:Name="btnAdd" />
-->
</GridView>
And, how can I add a ADD button(grid item) to XAML? thanks
You can achieve that by using a DataTemplateSelector, basically what you need to do is :
define another class that will represent the GridView "addItem"
public class GridItem
{
public String Subject { get; set; }
public String TargetDate { get; set; }
}
public class AddGridItem : GridItem
{
public bool IsGridItem { get; set; }
}
Make sure that your GridView's ItemSource collection has always an AddGridItem in it
private ObservableCollection<GridItem> _gridItems =new ObservableCollection<GridItem>()
{
new GridItem()
{
Subject = "Subject1",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject2",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject3",
TargetDate = "TargetDate"
},new AddGridItem()
{
IsGridItem = true
}
};
public ObservableCollection<GridItem> GridItems
{
get
{
return _gridItems;
}
set
{
if (_gridItems == value)
{
return;
}
_gridItems = value;
}
}
Create a DataTemplateSelector class that will return the appropriate DataTemplate based on the Item type
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate RegularTemplate { get; set; }
public DataTemplate AddTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item,
DependencyObject container)
{
if (item is AddGridItem)
return AddTemplate;
if (item is GridItem)
return RegularTemplate;
return base.SelectTemplateCore(item, container);
}
}
Define your dataTempaltes and a DataTemplateSelector as staticresources to use them in your GridView
<Page.Resources>
<DataTemplate x:Key="RegularTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border BorderThickness="3" BorderBrush="White">
<StackPanel VerticalAlignment="Bottom" Background="LightSkyBlue">
<TextBlock Text="{Binding Subject}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="AddItemTemplate">
<Border BorderThickness="3" BorderBrush="White" Background="DodgerBlue">
<FontIcon Glyph="" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
</Border>
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
RegularTemplate="{StaticResource RegularTemplate}"
AddTemplate="{StaticResource AddItemTemplate}">
</local:MyDataTemplateSelector>
</Page.Resources>
<Grid>
<GridView ItemsSource="{Binding GridItems}" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">
</GridView>
</Grid>

How to Make Content Hidden in Expander Windows Phone Control

I am playing around with an example of Expander Control from Windows Phone Toolkit (I am using it for wp7).
When I load up the stripped down version everything seems expanded. When I click on Customer Pizza or 2 nothing happens. I would like the sub stuff to be collapsed but I don't know how.
<phone:PhoneApplicationPage
x:Class="ExpanderViewSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<toolkit:RelativeTimeConverter x:Key="RelativeTimeConverter"/>
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Stretch="None"/>
<TextBlock Text="{Binding Name}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilySemiLight}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CustomExpanderTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Stretch="None"/>
<TextBlock Foreground="{StaticResource PhoneSubtleBrush}" VerticalAlignment="Center"
FontSize="{StaticResource PhoneFontSizeNormal}">
<TextBlock.Text>
<Binding Path="DateAdded" Converter="{StaticResource RelativeTimeConverter}" StringFormat="Date added: {0}" />
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="WindowsPhoneGeek.com" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="ExpanderViewSample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle2Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="listBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}"
IsExpanded="False"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"></toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
List<CustomPizza> customPizzas = new List<CustomPizza>()
{
new CustomPizza()
{
Name = "Custom Pizza 1",
IsExpanded = false,
DateAdded = new DateTime(2010, 7, 8),
Image="Images/pizza1.png"
},
new CustomPizza() { Name = "Custom Pizza 2", DateAdded = new DateTime(2011, 2, 10), Image="Images/pizza2.png"}
};
this.listBox.ItemsSource = customPizzas;
// Important properties:
// IsExpanded
// Header
// Expander
// ItemsSource
// HeaderTemplate
// ExpanderTemplate
// ItemTemplate
// NonExpandableHeader
// IsNonExpandable
// NonExpandableHeaderTemplate
}
}
public class CustomPizza : INotifyPropertyChanged
{
private bool isExpanded;
public string Image
{
get;
set;
}
public string Name
{
get;
set;
}
public DateTime DateAdded
{
get;
set;
}
public bool IsExpanded
{
get
{
return this.isExpanded;
}
set
{
if (this.isExpanded != value)
{
this.isExpanded = value;
this.OnPropertyChanged("IsExpanded");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I also don't get what this really is for
ExpanderView Header="{Binding}" Expander="{Binding}"
I don't get what "binding" is referring too. It just seems to know which data to use but I don't know how it knows.
To change the expanded state of the expander view you can do the following
-register for tap event and add binding to IsExpanded (this will bind to the IsExpanded property of CustomPizza)
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}"
IsExpanded="{Binding IsExpanded}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"
Tap="expander_OnTap"></toolkit:ExpanderView>
-in the tap event switch the IsExpanded flag of the CustomPizza:
private void expander_OnTap(object sender, System.Windows.Input.GestureEventArgs e)
{
ExpanderView expander = sender as ExpanderView;
CustomPizza customPizza = expander.DataContext as CustomPizza;
customPizza.IsExpanded = !customPizza.IsExpanded;
}
Regarding the question about ExpanderView Header="{Binding}" Expander="{Binding}", when you set (or bind) the ItemsSource property of an ItemsControl to a list (ListBox is inheriting from a ItemsControl), the DataTemplate inside the ItemTemplate will be automatically set to each individual item. For example here you are setting it to a List of CustomPizza so each ItemTemplate DataContext will be a CustomPiza. So the ExpanderView will have the CustomPizza as DataContext. {Binding} will just pass the DataContext so like this whatever is inside the HEaderTemplate will get the same DataContext (CustomPizza ). If you had put {Binding Image} then the HeaderTemplate will just have the Image string as DataContext.

validate a cell based on another cell value in datagrid in silverlight

PFB the code for datagrid in our silverlight app,i need to validate the column AttributeValue in each row based on other column value DatatypeName, for example the DatatypeNamecolumn value for a particular row is int the AttributeValue column in the same row should allow user only int ,if user enters other than int the cell should throw validation exception.Please help
<sdk:DataGrid Margin="0,0,0,50" Grid.Row="1" Grid.Column="0" RowStyle="{StaticResource DataGridRowStyle1}" Style="{StaticResource DataGridStyle1}" IsReadOnly="True" Foreground="{StaticResource GrayBrush}" HorizontalScrollBarVisibility="Hidden" Name="dgKpiAttributes" MinHeight="5" VerticalAlignment="Stretch" FontSize="13.333" FontFamily="Segoe UI" AutoGenerateColumns="False" GridLinesVisibility="None" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header=" " >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkSelect"
VerticalAlignment="Center" IsChecked="False" HorizontalAlignment="Center" HorizontalContentAlignment="Center"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="AttributeName" SortMemberPath="AttributeName" Width="50*" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center">
<TextBlock x:Name="txtAttributeName" TextWrapping="Wrap" Padding="4" Text="{Binding AttributeName}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="AttributeValue" SortMemberPath="AttributeValue" Width="80*" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center">
<TextBox x:Name="AttributeValue" Margin="0,0,10,0" HorizontalAlignment="Stretch" Text="{Binding AttributeValue}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="DataType" SortMemberPath="DataTypeName" Width="50*">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center">
<TextBox x:Name="DatatypeName" HorizontalAlignment="Stretch" TextWrapping="Wrap" IsEnabled="False" Text="{Binding DataTypeName}" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
Well, from your code I can see your class is like this (correct me if I'm mistaken):
class MyClass
{
public string AttributeName {get;set;}
public string AttributeValue {get;set;}
public string DatatypeName {get;set;}
}
In silverligth, I suppose there is a way to check another cells in the same row in a datagrid, but since you are working with bindings, you do not need that, you can work directly in your data object:
class MyClass
{
public string AttributeName {get;set;}
public string DatatypeName {get;set;}
private string _AttributeValue;
public string AttributeValue {
get{
return _AttributeValue;
}
set{
if (validate(DatatypeName,value)){
//Do something if validation is a success
_AttributeValue = value;
}
else{
//Do something if validation fails
}
}
}
bool validate(string typename,string value){
//do your validation, return true or false
return true
}
}
This way you do not need to concern yourself with traversing the UI, only with the data.