DataTemplateSelector won´t get used - wpf

To switch between two ItemTemplates in my ListView based on the current Item type, I implemented a DataTemplateSelector. I added it via Binding to the ListView. But if I set a breakpoint, it never gets called. I tried everything, nothing works.
public class ListViewTemplateSelector : DataTemplateSelector
{
public DataTemplate SectionTemplate { get; set; }
public DataTemplate EntryTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is Section)
{
return SectionTemplate;
}
if (item is Entry)
{
return EntryTemplate;
}
return base.SelectTemplate(item, container);
}
}
XAML:
<ListView DataContext="{Binding ElementName=This}" x:Name="list" Margin="200,25,0,0" ItemsSource="{Binding CurrentSelection}" ItemTemplateSelector="{StaticResource TemplateSelector}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}" Width="100" />
<GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}" Width="300" />
</GridView>
</ListView.View>
</ListView>
<DataTemplate x:Key="sectionTemplate">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Source="\Icons\blue-folder.png" />
<TextBlock Text="{Binding ID}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="entryTemplate">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Source="\Icons\ui-text-field-medium.png" />
<TextBlock Text="{Binding ID}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
<sdk:ListViewTemplateSelector x:Key="TemplateSelector" SectionTemplate="{StaticResource sectionTemplate}" EntryTemplate="{StaticResource entryTemplate}" />
Has anybody an idea how to fix that?
Thanks R

From GridView Overview > GridView Layout and Style > Defining and Styling Columns in a GridView:
When defining the data field to display in a GridViewColumn, use the
DisplayMemberBinding, CellTemplate, or CellTemplateSelector
properties. The DisplayMemberBinding property takes precedence over
either of the template properties.
Hence you would have to remove the DisplayMemberBinding from your GridViewColumns and set the CellTemplateSelector instead of the ListView's ItemTemplateSelector:
<GridView>
<GridViewColumn Header="ID" Width="100"
CellTemplateSelector="{StaticResource TemplateSelector}"/>
<GridViewColumn Header="Value" Width="300"
DisplayMemberBinding="{Binding Value}"/>
</GridView>

Related

get selected item ID from list view when click a button on the list view

Below is xaml and ListView:
<ListView x:Name="lvImages" ItemsSource="{Binding Path=resimGuncelle}" SelectedItem="{Binding Path=ID}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Name="MyImage" Source="{Binding RESIM_YOLU}" Width="120" Height="110" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Title" DisplayMemberBinding="{Binding FileName}" x:Name="txtx" x:Uid="dd" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Style="{StaticResource DaireButtonResimSil}" x:Name="btndil" Click="btndil_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I want to get Selected item ID , something like this:
private void btndil_Click(object sender, RoutedEventArgs e)
{
var selectedImageId = ((ResimGuncelleme)lvImages.SelectedItem).ID;
}
If i am getting this right, you have an ItemDataModel for your ListView items, and it has an Id property. Each time you click on a row predefined button you want to get that row item's Id property (without selecting the row, otherwise you could simply check the ListView's SelectedItem property).
Assuming your ItemModel looks something like this:
public class ItemModel
{
public string Id { get; set; }
public BitmapSource ResimYolu { get; set; }
public string FileName { get; set; }
}
In your xaml you could pass the item where the button was clicked in the Button's Tag using a RelativeSource binding:
<Grid>
<ListView x:Name="lvImages" ItemsSource="{Binding Path=ResimGuncelle}" SelectedItem="{Binding Path=Id}">
<ListView.View>
<GridView>
<GridViewColumn Header="Image">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Name="MyImage" Source="{Binding ResimYolu}" Width="120" Height="110" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Title" DisplayMemberBinding="{Binding FileName}" x:Name="txtx" x:Uid="dd" />
<GridViewColumn Header="Button">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btndil" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}}" Content="Button" Click="btndil_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
And you can get that item's id from your button's click handler:
private void btndil_Click(object sender, RoutedEventArgs e)
{
var item=((sender as Button)?.Tag as ListViewItem)?.DataContext;
var itemId = (item as ItemModel)?.Id;
}
Ps: this isn't a very clean way to do that!

Multiline WPF ListViewItem

I have a ListView that I need to populate with some text data.
Currently my ListViewItem look this way (2 columns):
Name Number of files Files finished
XAML:
<ListView.View>
<GridView>
</GridView>
</ListView.View>
Here i have all my GridViewColumnHeader and my Binding data for example Name property:
<!-- file name column -->
<GridViewColumn>
<GridViewColumnHeader Content="File name" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn>
What i want to do now is to see my Name in first line and NumberOfFiles and FilesFinished in second line:
So after quick search i found this solution.
So i add this:
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding NumberOfFiles}" />
<TextBlock Text="{Binding FilesFinished}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
So after add my files into my ListView i cannot see any file, so i try to remove my ListView.View and still the files missing.
What i dong wrong ?
It's look fine. I just add listview name.
<Grid>
<ListView Name="ListViewFiles">
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Authors">
<GridViewColumn Header="File name" Width="120" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="NumberOfFiles" Width="120" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding NumberOfFiles}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Code Sample. Maybe you forget ListViewFiles.ItemsSource = items;
public MainWindow()
{
InitializeComponent();
List<File> items = new List<File>();
items.Add(new File() { Name = "File One", NumberOfFiles = 2, Filesfished = "Yes" });
items.Add(new File() { Name = "File Two", NumberOfFiles = 2, Filesfished = "No" });
ListViewFiles.ItemsSource = items;
}
public class File
{
public string Name { get; set; }
public int NumberOfFiles { get; set; }
public string Filesfished { get; set; }
}

Wpf ViewList, how to set check box = isChecked to true, when a row is selected?

I could use some advice to set checkBox to isChecked = true when you select a row as a user. Have created a Listview, that has some GridViewColumns. One of these Columns has a checkBox inside. It look like this image:
The user can set the selected by clicking inside the CheckBox and thats okay. What I also want is that when the user select a row, like the blue one, the checkBox should be selected (Selected when blue, and unselected if you unselect it ofc)
In my Customer Model, I have one property which uses the INotifyPropertyChanged event.
// Room Selected property.
public bool Selected
{
get
{
return isChecked;
}
set
{
isChecked = value;
OnPropertyChanged("Selected");
}
}
I'm using this property to see what the user has selected when clicking further in my application.
Can you do something smart, so I still keep the property to the CustomerModel?
ListView code
<ListView Height="250" Width="Auto" ItemsSource="{Binding CustomerList}" Grid.Row="1" SelectionMode="Multiple" HorizontalAlignment="Center">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView >
<GridViewColumn Header="ID" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" TextAlignment="Center" Width="40"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Header="First name" Width="130"/>
<GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="Last name" Width="130"/>
<GridViewColumn DisplayMemberBinding="{Binding PhoneNumber}" Header="Phone" Width="130"/>
<GridViewColumn DisplayMemberBinding="{Binding Email}" Header="Email" Width="250"/>
<GridViewColumn Header="Selected" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Selected}"></CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Also the CustomerLits which is loaded inside the ListView is of type ObservableCollection.
Good day.
Update:
Have tried to create the start of a command.
SelectedChangeCommand = new RelayCommand(SelectedChangedCommand_DoWork, () => true);
// Selectionchanged Command
void SelectedChangedCommand_DoWork(object obj)
{
}
Now I'm not so sure what to do..
You can do it all in the XAML.
Set the IsChecked of the checkbox property binded to the listview selectedItem with a converter. If selectedItem is null return false otherwise return true.
You will end up with something like this:
<ListView Height="250" Name="myListView" Width="Auto" ItemsSource="{Binding CustomerList}" Grid.Row="1" SelectionMode="Multiple" HorizontalAlignment="Center">
....
<CheckBox IsChecked="{Binding ElementName=myListView, Path=SelectedItem, Converter={StaticResource MyConverter}"></CheckBox>
Give it a try :)

WPF Progress bar in ListView remained empty and add new data

I want implement ProgressBar insine my ListView:
<ListView Name="lvTest" ItemsSource="{Binding PersonList}" Margin="308,45,268,473">
<ListView.View>
<GridView>
<GridViewColumn Width="390" Header="File name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="50" Header="Progress">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ProgressBar Maximum="100" Value="{Binding Progress}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
My class example:
internal class MyData
{
public string Name { get; set; }
public int Progress { get; set; }
}
And the code behind:
var items = new ObservableCollection<MyData>();
items.Add(new MyData() { Name = "Some", Progress = 25 });
items.Add(new MyData() { Name = "Another", Progress = 91 });
lvTest.ItemsSource = items;
And this is the result: http://s12.postimg.org/3mgcwqbvh/image.png
As you can see my progress bar is empty and all i can see is dot inside.
Here with text in the progressbar.
<ListView Name="lvTest">
<ListView.Resources>
<DataTemplate x:Key="MyDataTemplate">
<Grid Margin="-6">
<ProgressBar Maximum="100" Value="{Binding Progress}" Width="{Binding Path=Width, ElementName=ProgressCell}" Height="10" Margin="0"/>
<TextBlock Text="{Binding Progress, StringFormat={}{0}%}" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="390" Header="File name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn x:Name="ProgressCell" Width="50" Header="Progress" CellTemplate="{StaticResource MyDataTemplate}" />
</GridView>
</ListView.View>
</ListView>
The Problem is the size of the Cell. Your ProgressBar is visible - but all you can see is the little dot.
Bind the ProgressBar Width to the Width of the Cell.
<ListView Name="lvTest">
<ListView.View>
<GridView>
<GridViewColumn Width="390" Header="File name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn x:Name="ProgressCell" Width="50" Header="Progress">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ProgressBar Maximum="100" Value="{Binding Progress}" Width="{Binding Path=Width, ElementName=ProgressCell}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Adding a width property to the progress bar should solve your issue, i.e.
<ProgressBar Maximum="100" Value="{Binding Path=Progress}" Width="100"/>

How to set ListView selection from the template element that has focus?

I have a ListView that uses data templates to display specific controls within the cells:
<ListView Grid.Row="1" ItemsSource="{Binding Ratings}" SelectedItem="{Binding SelectedRating}" Margin="5" MinHeight="50" SelectionMode="Single" ScrollViewer.CanContentScroll="True"
local:GridViewSort.Enable="True">
<ListView.View>
<GridView>
<GridViewColumn Header="Date" local:GridViewSort.PropertyName="RatingDate">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding RatingDate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Rating ID" local:GridViewSort.PropertyName="RatingID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding RatingID}" Width="35" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" local:GridViewSort.PropertyName="RatingName">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding RatingName}" Width="35" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Age" local:GridViewSort.PropertyName="RatingAge">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding RatingAge}" Width="35" />
<TextBlock Text=" yrs"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I also have a delete button to remove the selected row.
My user has a habit of clicking into to the edit and date controls (which doesn't change the selected row) and then hitting delete to remove the row he has clicked on. Unfortunately, this deletes the wrong row.
How can I change the row selection whenever the user clicks into the controls?
You can use PreviewMouseUp event on a ListViewItem:
<ListView Grid.Row="1" ItemsSource="{Binding Ratings}" SelectedItem="{Binding SelectedRating}" Margin="5" MinHeight="50" SelectionMode="Single" ScrollViewer.CanContentScroll="True"
local:GridViewSort.Enable="True">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewMouseUp" Handler="ListViewItem_PreviewMouseUp" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
...
Code behind:
private void ListViewItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
var listViewItem = sender as ListViewItem;
if (listViewItem != null)
{
listViewItem.IsSelected = true;
}
}

Resources