How to bind booleans to DataTemplate - wpf

I have this DataTemplate for my RadGridView with a binding:
<DataTemplate x:Key="StatusTemplate">
<local:StatusIndicator Style="{StaticResource StatusIndicator}" IsEnabled="{Binding}" />
</DataTemplate>
I'm using it on my GridViewDataColumn like this, where I bind booleans from my ItemsSource:
<telerik:GridViewDataColumn DataMemberBinding="{Binding Enabled}" CellTemplate="{StaticResource StatusTemplate}" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding Connected}" CellTemplate="{StaticResource StatusTemplate}" />
But the Enabled and Connected properties assigned to the DataMemberBinding is not working,

I am afraid you won't be able to use the same DataTemplate for both columns. The binding path cannot be "injected" into the template in XAML which means that will need to create a unique DataTemplate with a specific binding path for each column:
<telerik:GridViewDataColumn DataMemberBinding="{Binding Enabled}">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<local:StatusIndicator Style="{StaticResource StatusIndicator}" IsEnabled="{Binding Enabled}" />
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
<telerik:GridViewDataColumn DataMemberBinding="{Binding Connected}">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<local:StatusIndicator Style="{StaticResource StatusIndicator}" IsEnabled="{Binding Connected}" />
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
If the DataTemplate is more complicated, you might consider creating the templates and replace the binding path programmatically:
Combining DataTemplates at runtime

Related

WPF Datagrid MouseBinding MVVM

I managed to handle a double click on one of my datagrid rows to execute a command on my viewmodel by this xaml:
This works perfect when I click somewhere in the area of the first column (which is bound to the readonly ID), but fails when the double click is done in the area of the textbox in column two (CustomerNumber, which of course catches the doubleclick).
Which would be a MVVM-like way to handle doubleclicks for both scenarios?
You could replace the DataGridTextColumn with a DataGridTemplateColumn and add a MouseBinding to the TextBox in the CellEditingTemplate:
<DataGridTemplateColumn Header="Customer Number">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CustomerNumber}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding CustomerNumber}">
<TextBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</TextBox.InputBindings>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Binding textboxes inside a usercontrol to datagrid

Is the way that I'm binding the UserControl to the DataGrid correct?
In my MainWindow I have a datagrid (code below):
<DataGrid x:Name="MusicListGrid" ItemsSource="{Binding MusicList}" AutoGenerateColumns="False" IsSynchronizedWithCurrentItem="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Artist" Binding="{Binding Artist,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Album" Binding="{Binding Album,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Track" Binding="{Binding Track,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>
The usercontrol inside my MainWindow, that I'm binding to the selected item of the datagrid:
DataTemplate(in MainWindow):
<Window.Resources>
<DataTemplate x:Key="MusicDetailListTemplate" >
<v:MusicDetailView DataContext="{Binding ElementName=MusicListGrid,Path=SelectedItem}" />
</DataTemplate>
</Window.Resources>
ContentControl(in MainWindow):
<ContentControl x:Name="musicDetail" Content="{Binding}" ContentTemplate="{StaticResource MusicDetailListTemplate}" Grid.Column="1" />
The textboxes inside my UserControl looks like this:
<TextBox Grid.Column="1" Grid.Row="0" Width="200" Margin="10,5" Text="{Binding Artist,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Column="1" Grid.Row="1" Width="200" Margin="10,5" Text="{Binding Album,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Column="1" Grid.Row="2" Width="200" Margin="10,5" Text="{Binding Track,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
This works, but I'm not sure if I'm doing the correct way?
Can I also bind a textbox to the datagrid like this:
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Path=MusicListGrid.Artist.SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
The data in the datagrid is an ObservableCollection<Music> (music is my model).
If I replace my UserControl with a tabcontrol, should I have the tabcontrol be a separate view or just be part of MainWindow? And have the content of the tabcontrol be separate views? I was thinking of having the datagrid and a tabcontrol with 2 tabs, one for editing and the other for displaying (to look more presentable).
Sorry if these are very basic questions, I just want to be on the right path.
It is more common to set the Content property of the ContentControl element to the data object:
<ContentControl x:Name="musicDetail" Content="{Binding ElementName=MusicListGrid,
Path=SelectedItem}" ContentTemplate="{StaticResource MusicDetailListTemplate}" />
The DataContext defines what the data of the relevant type should look like in the UI, so you shouldn't really set the DataContext there... it is automatically set to the relevant data object instance... it should look more like this (where Prefix is the XML Namespace Prefix that you set up for your project and YourClass is the type of object in the DataGrid):
<Window.Resources>
<DataTemplate x:Key="MusicDetailListTemplate" DataType="{x:Type Prefix:YourClass}">
<v:MusicDetailView DataContext="{Binding}" />
</DataTemplate>
</Window.Resources>

WPF binding Listbox layoutpanel

I´m using devexpress and I want to do a binding with a Listbox, but I have an error. Here my code:
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<dxd:LayoutPanel
Caption="{Binding nameList}"
AllowHide ="False" AllowFloat="False"
GotFocus="panel_GotFocus" >
<TextBox Text="Hello" />
</dxd:LayoutPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
With this code, Caption {Binding nameList} is empty.
I have tried this.
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding nameList}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, text in TextBox is correct, I need to use the first code.
You seem to be a bit confused about how to use this ListBox. First, you need a collection property to bind to the ListBox.ItemsSource property. Let's say you have a collection of User objects called Users:
<ListBox ItemSource="{Binding Users}" />
Now we want to define how each User should be displayed... all the properties of the User class will be available to the Binding inside the DataTemplate. Let's say that the User class has two properties; Name and Age:
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
Then putting it all together:
<ListBox ItemSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Create Common DataGridTemplateColumn in WPF

I need to create a common DataGridTemplateColumn, so that I can use it across my application with different objects and properties.
here is some sample code, I use in my project
<DataGridTemplateColumn Width="100*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
I need a generic version of the code so that I can place the DataTemplate in app.xaml and reference it in my code
You can't template DataGridTemplateColumn directly. But fortunately you can use global templates for cells. Take a look at example:
App.xaml
<Application.Resources>
<DataTemplate x:Key="CellEdintingTemplate">
<TextBox Text="{Binding Path=Age}" />
</DataTemplate>
<DataTemplate x:Key="CellTemplate">
<TextBlock Text="{Binding Path=Age}" />
</DataTemplate>
</Application.Resources>
Using
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn
CellEditingTemplate="{StaticResource CellEdintingTemplate}"
CellTemplate="{StaticResource CellTemplate}" />
</DataGrid.Columns>
</DataGrid>

How to trigger DataGridevents DataGridBeginningEdit, DataGridCellEditEnding with a Combobox in Silverlight? / CellTemplate for a Combobox

I want to use the DataGridevents (DataGridBeginningEdit, DataGridCellEditEnding, ..etc) to handle and detect changes. As far as I understood, without a "CellTemplate" these are not triggered. So I am trying to create an appropriate celltemplate using a TextBlock, but I guess it is not very straightforward with the binding I am using for the Combobox in the CellEditingTemplate, because I am using "DisplayMemberPath"..
There are examples of simpler cases but I couldn't find smth for this scenario. See Xaml snippet below;
<data:DataGridTemplateColumn Width="100">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Center" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding DurationTypeList, Source={StaticResource itemSourceProvider}}"
SelectedValuePath="Code"
SelectedValue="{Binding Path=DurationTypeCode, Mode=TwoWay}"
DisplayMemberPath="Template" />
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
Thank you
It turns out, i have two options..
Solution #1
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Left" Text="{Binding Path=DurationType.Template, Mode=OneWay}" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding DurationTypeList, Source={StaticResource itemSourceProvider}}"
SelectedValuePath="Code"
SelectedValue="{Binding Path=DurationType, Mode=TwoWay}"
DisplayMemberPath="Template" />
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
I changed the binding path from string to the object with Code and Template properties..
This blog helped a lot..

Resources