XAML: Same Template, Different Bindings - c#

I am trying to create a ListView with a GridView that has 2 columns: Name and Date, which are to be binded to a Person Object later on.
I want to use a DataTemplate, this template consists of a Label.
My problem is I want to use this template for both columns, but the content of the label is to be bind to a different property in each column. In short, I want to be able to bind the content of the label, in the GridViewColumn code block and not in the DataTemplate code block.
Thanks in advance for your help.

I tried it this way with empty binding in datatemplate which solved in my case..(didn't checked for object types with more than one property to be binded). This will work in the case of this question's context.
<DataTemplate x:Key="commonTemplate">
<Label Content="{Binding}" />
</DataTemplate>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Name}"
ContentTemplate="{StaticResource commonTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Date}"
ContentTemplate="{StaticResource commonTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Any better way or improvements are always welcome.. thank you

Related

MVVM - select item in TreeView and show its properties on a ListView using binding

I'm new to MVVM. I created a TreeView with hierarchy of 3 levels: level1: Program, level2: Action, level3: Position. I also created a ListView under the TreeView (see xaml) . Right now the items of the ListView are not bound to anything (the names "Type", "Speed" are only placeholders.)
When selecting an item from level2 (Action) in the TreeView, i'd like to see it's properties (type, speed) appear on the ListView below.
Is there a way to do it through a change in the View only (xaml), without using code in the ViewModel ? maybe there's a way to use a certain binding, that can be changed when pressing on the item in the TreeView?
xaml (model):
<TreeView
Grid.Row="0"
x:Name="MainTreeView"
HorizontalAlignment="Stretch"
Margin="10"
VerticalAlignment="Stretch"
ItemsSource="{Binding Programs}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Actions}" DataType="{x:Type VM:ProgramVM}">
<Label Content="{Binding ProgramName}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Poses}" DataType="{x:Type VM:ActionVM}">
<Label Content="{Binding Actiontype}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type VM:PositionVM}">
<Label Content="{Binding PosName}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ListView Grid.Row="1" Margin="10" Name="lvUsers">
<ListView.View>
<GridView>
<GridViewColumn Header="Type" Width="100" DisplayMemberBinding="{Binding Type}" />
<GridViewColumn Header="Speed" Width="100" DisplayMemberBinding="{Binding Speed}" />
</GridView>
</ListView.View>
</ListView>
This is a well known issue with the treeview in WPF. You have to create an 'is selected' property for each object in your tree so that you know what the user has chosen, then you can just show the selected object in your listview.
It's been a while since I played with a treeview, but here are some of the links that I think helped me in the past.
Data binding to SelectedItem in a WPF Treeview
WPF MVVM TreeView SelectedItem

How to access element (Combo Box) in XAML from code behind

How do I access a control in XAML that is nested in a GridViewColumn.CellTemplate? By accessing the combo box I want to set its ItemsSource in the code behind.
Code:
<GridViewColumn Width="80">
<GridViewColumnHeader Content="UseCLUT"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Path=UseCLUT}" Style="{StaticResource GridBlockStyle}"/>
<ComboBox x:Name="combTrueFalse" SelectedItem="{Binding Path=UseCLUT}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I have named the comboBox as combTrueFalse and tried to referenced it in the code behind but it could not be found.
I find a work around to the problem.
I have set the collection of the combo box to a class which contains the collection for the combox's selection.
The mainWindow class contains the data class's variable.
ItemsSource="{Binding ElementName=mainWindow, Path=data.comboxTFSmall}"
Meaning to say I have set the combox's item towards a Class which contains the collection and not from the code behind.
<GridViewColumn Width="80" >
<GridViewColumnHeader Content="UseCLUT"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Path=UseCLUT, Mode=TwoWay}" Style="{StaticResource GridBlockStyle}"/>
<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=data.comboxTFSmall}" SelectedValue="{Binding Path=UseCLUT}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Please do correct me if you find that my explanation is misleading thanks.
regards

Can't show image and textblock inside a GridView

This is my simple code to do this:
<Grid>
<ListView>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Source="c:\myimage.jpg" />
<TextBlock Text="Image Name"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
But except the empty header, nothing shows up.
This is my first time using GridView. Am I missing something ?
Your ListView has no items, the CellTemplate is applied to each item in the list and if there are no items nothing will be shown. Did you perhaps mean to change the Header instead?
If you are not binding a source then it is not going to generate any rows. Show your XAML or code behind for binding a source.
You probably don't want to use CellTemplate. Here is an intro-level example of ListView: http://www.switchonthecode.com/tutorials/wpf-tutorial-using-the-listview-part-1

ListView + MultipleSelect + MVVM =?

If I were to say "the heck with it!", I could just give my ListView with SelectionMode="Multiple" a name, and be able to get all of the selected items very easily. But I'm trying to stick to MVVM as much as possible, and I want to somehow databind to an ObservableCollection that holds the value from the Name column for each selected item. How in the world do you do this? Single selection is simple, but the multi selection solution is not obvious to me with my current WPF / MVVM knowledge.
I read this question on SO, and while it does give me some good insight, I don't know how to add the necessary binding to a row, because I am using a ListView with a GridView as its View, not a ListBox.
Here's what my XAML basically looks like:
<ListView DockPanel.Dock="Top" ItemsSource="{Binding ClientPreview}" SelectionMode="Multiple">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Address">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Address}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
It sounds like the right thing to do is to databind each row's IsSelected property to each object stored in the ObservableCollection I'm databinding to. I just haven't figured out how to do this.
Write ItemContainerstyle on the ListView and put a Setter to do the binding to your ViewModel 'IsSelected' property
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected,Mode=OneWayToSource}"/>

How can I modify an instance of the button defined in a Cell Header?

I have the following XAML class:
<ListView Controls:ListViewColumns.Stretch="true"
Name="myListItems" SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.Header>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Name="btnDelete"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Padding="0"
Margin="0"
IsEnabled="{Binding Converter={StaticResource inverseBoolConverter},
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WO:OpCompTab}}, Path=DisableAll}"
Click="btnDelete_Click" Tag="{Binding Path=.}">
<Image Source="/Win7;component/Images/Icons/Remove.png"
Width="{StaticResource IconWidth}"
Height="{StaticResource IconHeight}" />
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The listview gets populated by hooking an observable collection up to its ItemSource property. This generates a neat looking column of Delete buttons for each item in the observable collection.
But this presents a quandary: How do I access the "btnDelete" of an individual row of the ListView? I'd like to change its icon on a per-row basis. Is it just a matter of binding the observable collection to the cell template somehow?
Instead of hardcoding the Image.Source, bind it to a property in your row object. Another way is to create a value converter and pass in the row or some property if you can't or don't want to modify the row object to add an ImageSource property. Have the value converter return the correct image source based on the passed in property or some other logic.

Categories

Resources