How to change WPF listview row background colour dynamically? - wpf

I am new to WPF, I have the following xaml code for list view:
<ListView x:Name="listView1" ItemsSource="{Binding Processes1}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="470" Margin="10,95,150,6" Width="565" SelectionChanged="NetscalerCfgView_listView1_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Line" DisplayMemberBinding="{Binding srcCfgLineNum}"/>
<GridViewColumn Header="Source Config" DisplayMemberBinding="{Binding srcConfigText}"/>
</GridView>
</ListView.View>
</ListView>
I have the class SrcListViewInfo which I am displaying in listview:
public class SrcListViewInfo
{
public int srcCfgLineNum { get; set; }
public string srcConfigText { get; set; }
}
I have declared it in windows load event like this:
public ObservableCollection<SrcListViewInfo> processes1 = null;
processes1 = new ObservableCollection<SrcListViewInfo>();
I want to color the row background dynamically in a different function under different cases dynamically, for example:
case DiffResultSpanStatus.DeleteSource:
for (i = 0; i < drs.Length; i++)
{
SrcListViewInfo newInfo = new SrcListViewInfo();
newInfo.BackgroundColor = new SolidColorBrush(Colors.Red);
// newInfo.BackgroundColor = Brushes.Red;
newInfo.srcCfgLineNum = cnt;
newInfo.srcConfigText = ((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line;
// newInfo.BackgroundColor = Brushes.Red; << want to set the color like this.
I have tried solid brush but it does not seem to be working correctly.

You can Style the ListViewItem in xaml directly,
Example:
Assuming your "Name" variable is a string, you can try
<ListView Name="whatever">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Name}"
Value="John">
<Setter Property="Background"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
....
Now any ListView Row with "Name" Value of "John" will have a "Red" Background

an option
is to use IMultiValueConverter in ListView.ItemTemplate
<ListView DataContext="{Binding}" ItemsSource="{Binding Models}" AlternationCount="3" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name }"/>
<TextBlock Text="{Binding Desc }"/>
<StackPanel.Background>
<MultiBinding Converter="{StaticResource BackConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}"/>
</MultiBinding>
</StackPanel.Background>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class BackConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// write your logic (You have the model and the view model)
var index = ((ItemsControl)values[1]).Items.IndexOf(values[0]);
if (index % 2 == 0)
return Brushes.Gray;
return Brushes.White;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
another option
is to use ItemsControl.AlternationIndex in ListView.ItemContainerStyle
<ListView DataContext="{Binding}" ItemsSource="{Binding Models}" AlternationCount="3" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Green" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="2">
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Edit
public MainWindow()
{
InitializeComponent();
lv.ItemsSource = new List<string> { "a", "b", "c", "d", "e" };
}

After some googling i found out my own solution I am using Listview.ItemsSource and as source i use List with ListViewItems Then i can set background of specify ListViewItem in List, and just refresh listview.
XAML:
<ListView x:Name="listView" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1">
<ListView.View>
<GridView>
<GridViewColumn Header="IP" DisplayMemberBinding="{Binding IP}" Width="Auto"/>
<GridViewColumn Header="PING" DisplayMemberBinding="{Binding Ping}" Width="Auto"/>
<GridViewColumn Header="Host Name" DisplayMemberBinding="{Binding DNS}" Width="Auto"/>
<GridViewColumn Header="Mac" DisplayMemberBinding="{Binding MAC}" Width="Auto"/>
<GridViewColumn Header="Výrobce" DisplayMemberBinding="{Binding Manufacturer}" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
Fill ListView with Items with Gray Background:
List<ListViewItem> ITEMS = new List<ListViewItem>();
private void button_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 20; i++)
{
ListViewItem OneItem = new ListViewItem();
OneItem.Background = Brushes.LightGray;
OneItem.Content = new Device() { IP = "1.1.1.1", Ping = "30ms", DNS = "XYZ", MAC = "2F:3C:5F:41:F9", Manufacturer = "Intel" };
ITEMS.Add(OneItem);
listView.ItemsSource = ITEMS;
}
listView.Items.Refresh();
}
public class Device
{
public string IP { get; set; }
public string Ping { get; set; }
public string DNS { get; set; }
public string MAC { get; set; }
public string Manufacturer { get; set; }
}
Create Method for Row Change Color:
private void ChangeRowColor(int RowIndex,SolidColorBrush NewBackground)
{
ITEMS[RowIndex].Background = NewBackground;
listView.Items.Refresh();
}
And use it:
private void button1_Click(object sender, RoutedEventArgs e)
{
ChangeRowColor(4, Brushes.Green);
}

Related

How to get current cell value in GridView binding

Having spent the last few hours with this rather simple problem, I haven't yet found a way to do it. I'm using a GridView to display some data and need to perform some customization of the cell values using a converter. Here is the relevant XAML:
<ListView ItemsSource="{Binding SomeDataTable}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=XXX, Converter={StaticResource MyConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
What do I need to write in place of XXX above?
N.B. I cannot put constant column name here because this DataTemplate is to be used by all columns of GridView. I need a way to refer to current cell value just like how GridView's default template works when using DisplayMemberBinding.
I found a relevant post here, but that also doesn't have any working answer.
One option is to use DisplayMemberBinding to create the GridViewColumns and then to define your TextBlock's style as a resource of your ListView and to use a converter there.
Given a scenario where I have a list of persons and I want to color all the cells based on the person's age:
Data item:
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
public Person(int age, string name)
{
Age = age;
Name = name;
}
}
Creating the columns in XAML:
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Age}" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
The converter which changes cell background based on the age:
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((int) value < 20)
{
return Brushes.LightBlue;
}
return Brushes.LightGreen;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
Using the converter:
<ListView.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Background">
<Setter.Value>
<Binding Path="Age">
<Binding.Converter>
<local:MyConverter/>
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
Result:
Full XAML:
<ListView x:Name="MyItems" Loaded="MyItems_OnLoaded">
<ListView.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Background">
<Setter.Value>
<Binding Path="Age">
<Binding.Converter>
<local:MyConverter/>
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Age}" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
</ListView>

How to use GridViewComboBoxColumn and allow the user to edit?

I need to present a WPF GridView where one column is a Combobox, The user can select one value from the list or enter a new value so I set the IsComboBoxEditable to true but the problem is that if the user types a value that is not in the ItemsSource the Text is blank when the Combobox looses the focus.
Note : I don't want, when a new value is typed , this value to be
added to the ItemsSource. I only need to save it's string value in row
that bounded to it.
I also need DropDownOpened event, to populate it's ItemsSource.
Here is my code:
<telerik:GridViewDataColumn Header="Description">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<telerik:RadComboBox IsEditable="True" ItemsSource="{Binding Descriptions}" Text="{Binding Description1,Mode=TwoWay}" DropDownOpened="descriptionRadComboBox_DropDownOpened"/>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
Description1 is string property, and Descriptions is List of string that populate in runtime.(When DropDownOpened Event occurred)
Like you mentioned, your goal is, simply, to "Editable ComboBox".
(And, of course, you don't want to add new Item to ItemsSource)
<telerik:GridViewDataColumn UniqueName="description1" Header="Description">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description1}"></TextBlock>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
<telerik:GridViewDataColumn.CellEditTemplate>
<DataTemplate>
<telerik:RadComboBox Name="SLStandardDescriptionsRadComboBox" IsEditable="True"
ItemsSource="{Binding DataContext.SLStandardDescriptions, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
DisplayMemberPath="SLStandardDescriptionTitle" DropDownOpened="Description_DropDownOpened">
</telerik:RadComboBox>
</DataTemplate>
</telerik:GridViewDataColumn.CellEditTemplate>
</telerik:GridViewDataColumn>
Codebehinde :
private void RadGridView_CellEditEnded(object sender, GridViewCellEditEndedEventArgs e)
{
if (e.Cell.Column.UniqueName == "description1")
{
RadComboBox combo = e.Cell.ChildrenOfType<RadComboBox>().FirstOrDefault();
if (combo != null)
{
List<Description> comboItems = combo.ItemsSource as List<Description>;
string textEntered = e.Cell.ChildrenOfType<RadComboBox>().First().Text;
bool result = comboItems.Contains(comboItems.Where(x => x.DescriptionTitle == textEntered).FirstOrDefault());
if (!result)
{
comboItems.Add(new Description { DescriptionTitle = textEntered });
combo.SelectedItem = new Description { DescriptionTitle = textEntered };
}
if (_viewModel.AccDocumentItem != null)
{
if (e.Cell.Column.UniqueName == "description1")
_viewModel.AccDocumentItem.Description1 = textEntered;
}
}
}
}
Here is the solution for .net DataGrid control:
<DataGrid ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Title}" ></DataGridTextColumn>
<DataGridComboBoxColumn SelectedValueBinding="{Binding ComboItem.ID}" DisplayMemberPath="ComboTitle" SelectedValuePath="ID">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.ComboItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.ComboItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
<Setter Property="IsEditable" Value="True" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
Surely you can do this using Telerik DataGrid control as well.
And here is my ViewModel:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
ComboItems = new ObservableCollection<ComboItem>()
{
new ComboItem(){ID=1,ComboTitle="ComboItem1"},
new ComboItem(){ID=2,ComboTitle="ComboItem2"},
new ComboItem(){ID=3,ComboTitle="ComboItem3"}
};
Items = new ObservableCollection<Item>()
{
new Item(){ID=1,Title="Item1",ComboItem=ComboItems[0]},
new Item(){ID=2,Title="Item2",ComboItem=ComboItems[1]},
new Item(){ID=3,Title="Item3",ComboItem=ComboItems[2]}
};
}
public ObservableCollection<Item> Items { get; set; }
public ObservableCollection<ComboItem> ComboItems { get; set; }
}
public class Item
{
public int ID { get; set; }
public string Title { get; set; }
public ComboItem ComboItem { get; set; }
}
public class ComboItem
{
public int ID { get; set; }
public string ComboTitle { get; set; }
}

Binding Enum with entity not working

I have a table Called IGdaily with Field Trans_Category. I want to bind a DataGridComboBoxColumn displaying enum and binds its int value to datagrid cell Trans_Category.
My Enum
public enum Enm_Purch_Ret : short
{
Purchase = 1,
Sale = 2,
Return = 3
}
Viewmodel Vm_Purchase
public class Vm_Purchase : INotifyPropertyChanged
{
private IGoldEntities db = new IGoldEntities();
public ObservableCollection<IGdaily> Vm_IGdaily { get; set; }
public ObservableCollection<Enm_Purch_Ret> Vm_Enum_P_R { get; set; }
public Vm_Purchase()
{
Vm_IGdaily = new ObservableCollection<IGdaily>();
Vm_Enum_P_R = new ObservableCollection<Enm_Purch_Ret>(Enum.GetValues(typeof(Enm_Purch_Ret)).Cast<Enm_Purch_Ret>().ToList());
}
public ObservableCollection<IGdaily> IGDailys
{
get { return Vm_IGdaily; }
set { Vm_IGdaily = value; NotifyPropertyChanged(); }
}
public ObservableCollection<Enm_Purch_Ret> Enm_Purch_Rets
{
get { return Vm_Enum_P_R; }
set { Vm_Enum_P_R = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
In XAML
<Window.DataContext>
<local:Vm_Purchase/>
</Window.DataContext>
<DataGrid x:Name="DG" ItemsSource="{Binding IGDailys}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding GroupName}" Header="Name" Width="200"/>
<DataGridComboBoxColumn Header="Item/Metal" SelectedValueBinding="{Binding Trans_Category}" SelectedValuePath="{Binding Path=Enm_Purch_Rets, StringFormat='\{0:D\}'}" DisplayMemberPath="Enm_Purch_Ret">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Enm_Purch_Rets, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Enm_Purch_Rets , RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridTextColumn Binding="{Binding Trans_Category}" ClipboardContentBinding="{x:Null}" FontSize="14" Header="Metal Id" Width="100"/>
</DataGrid.Columns>
</DataGrid>
public partial class IGdaily
{
public int GDaily_Id { get; set; }
public int DailyMast_Id { get; set; }
public int ItemGroup_Id { get; set; }
public int Item_Id { get; set; }
public int Trans_Category { get; set; }
}
Please help what is my mistake in binding. I am new to MVVM pattern.
please explain
Thanks
You can't set an int property to a Enm_Purch_Ret value because there is no implicit conversion between these two types.
But you could use a converter class that peforms the conversion for you:
public class EnumConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Enm_Purch_Ret e = (Enm_Purch_Ret)value;
return (int)e;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int i = (int)value;
return (Enm_Purch_Ret)i;
}
}
Usage:
<DataGrid x:Name="DG" ItemsSource="{Binding IGDailys}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell" >
<DataGrid.Resources>
<local:EnumConverter x:Key="conv" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding GroupName}" Header="Name" Width="200"/>
<DataGridComboBoxColumn Header="Item/Metal"
SelectedItemBinding="{Binding Trans_Category, Converter={StaticResource conv}}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Enm_Purch_Rets, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Enm_Purch_Rets , RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridTextColumn Binding="{Binding Trans_Category}" ClipboardContentBinding="{x:Null}" FontSize="14" Header="Metal Id" Width="100"/>
</DataGrid.Columns>
</DataGrid>

Binding to attached property not working

I am trying to prepare template for DataGridColumnHeader. Template should be really simple.
Attached dependency property csdpp:CalendarProperties.EnumDay should only specific day that DataGridColumnHeader belong to and converter should then just return right label for that day.
If I set AncestorType to DataGridTextColumn (that is what I want) and leave the code like this:
<Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridTextColumn}, Mode=OneWay,
Path=(csdpp:CalendarProperties.EnumDay),
Converter={StaticResource IndexToDayLabelConverter}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
nothing happen. Converter is not even getting called.
But if I change code to this:
<Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}, Mode=OneWay,
Path=(csdpp:CalendarProperties.EnumDay),
Converter={StaticResource IndexToDayLabelConverter}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
(DatagridTextColumn switched by DataGrid, DataGrid has attached property too (below))
Converter is getting called and as value is passed attached property from DataGrid. Why is that working for DataGrid and not for DataGridTextColumn? Please help.
Code with DataGrid and DataGridTextColumn:
<DataGrid Grid.Row="1" Grid.Column="1"
x:Name="_shiftDataGrid"
ItemsSource="{Binding ElementName=Root, Path=PersonShiftgroupings.ShiftPersons}"
DataContext="{Binding ElementName=Root, Path=PersonShiftgroupings.ShiftPersons}"
AutoGenerateColumns="False"
csdpp:CalendarProperties.EnumDay="Fri">
<DataGrid.Columns>
<DataGridTextColumn
csdpp:CalendarProperties.EnumDay="Wed"
HeaderStyle="{StaticResource DayHeaderStyle}">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
Any help would be appreciated.
Like i stated in my comment above DataGridColumnHeader is in the VisualTree of DataGrid via
DataGridColumnHeaderPresenter and not in the VisualTree of DataGridColumn.
You can reach the Column through DataGridColumnHeader's Column property
Column
I didn't want to get into your implementation and logic because i'm sure there's a cleaner way of doing what ever it is you need done.
Here's a sample of what you need to get it working :
CS:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
public List<SomeItem> MyItems
{
get { return new List<SomeItem> { new SomeItem() , new SomeItem() , new SomeItem() , new SomeItem() }; }
}
}
public class SomeItem
{
public int First { get { return 1; } }
public int Second { get { return 2; } }
public int Third { get { return 3; } }
public int Forth { get { return 4; } }
}
public static class ASample
{
public static string GetMyProperty(DependencyObject obj)
{
return (string)obj.GetValue(MyPropertyProperty);
}
public static void SetMyProperty(DependencyObject obj, string value)
{
obj.SetValue(MyPropertyProperty, value);
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(string), typeof(ASample));
}
public class ColumnHeaderConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return string.Empty;
DataGridColumn c = (DataGridColumn)value;
string header = ASample.GetMyProperty(c);
return header;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML :
<Window.Resources>
<local:ColumnHeaderConverter x:Key="colConverter"/>
<Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding
RelativeSource={RelativeSource AncestorType=DataGridColumnHeader}, Mode=OneWay,
Path=Column , Converter={StaticResource colConverter} }"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<DataGrid AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource DayHeaderStyle}"
ItemsSource="{Binding MyItems}" local:ASample.MyProperty="DataGrid" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding First}" local:ASample.MyProperty="11"/>
<DataGridTextColumn Binding="{Binding Second}" local:ASample.MyProperty="22"/>
<DataGridTextColumn Binding="{Binding Third}" local:ASample.MyProperty="33"/>
<DataGridTextColumn Binding="{Binding Forth}" local:ASample.MyProperty="44"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
DataGridTextColumn is no ancestor of DataGridColumnHeader

WPF Listview Item Clicked Name

I have a listview with 5 columns. In the first column i insert an image in wich i have an event MouseClicked event. What i want to accomplish is when i click the image from row 5 , to get the name of item in row 5 - column 2;
This is my code so far :
<ListView x:Name="HistoryListB">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="#FF515050"/>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="true">
<Setter Property="Background" Value="#FF515050"/>
<Setter Property="BorderBrush" Value="#FF3B3A3A"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn Width="90" Header="Image" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Name="Favorite" Width="12" Height="12" Source="{Binding ImageSource}" MouseLeftButtonDown="Image_MouseLeftButtonDown" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="90" Header="Time Added" DisplayMemberBinding="{Binding Time}" />
<GridViewColumn Width="110" Header="Status" DisplayMemberBinding="{Binding Status}"/>
<GridViewColumn Width="290" Header="ItemTitle" DisplayMemberBinding="{Binding ItemTitle}"/>
<GridViewColumn Width="50" Header="Duration" DisplayMemberBinding="{Binding Duration}"/>
</GridView>
</ListView.View>
</ListView>
And i add items in listview like this. I have a class and a list like this :
public class HistoryItems
{
public string Time { get; set; }
public string Status { get; set; }
public string ItemTitle { get; set; }
public string Duration { get; set; }
public ImageSource ImageSource { get; set; }
}
IList<HistoryItems> SHistoryItems { get; set; }
And then add the items :
SHistoryItems = new List<HistoryItems>() {
new HistoryItems () {
Time = DateTime.Now.ToString("HH:mm:ss tt"),
Status = "Started Playing : ",
ItemTitle = StationL.StationName
}
};
foreach (var item in SHistoryItems)
HistoryListB.Items.Add(SHistoryItems);
And in my code i want to get the name of the item from same row but 2nd column :
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock1.Text = ?? THE NAME OF THE SECOND COLUMN IN THE SAME ROW ?? ;
}
You can use the Tag property of the Image to hold the HistoryItem then you can access through the sender argument in the event handler.
Example:
Xaml:
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Name="Favorite" Width="12" Height="12" Source="{Binding ImageSource}" Tag="{Binding}" MouseLeftButtonDown="Image_MouseLeftButtonDown" />
</DataTemplate>
</GridViewColumn.CellTemplate>
Code:
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var image = sender as Image;
if (image != null && image.Tag is HistoryItems)
{
TextBlock1.Text = (image.Tag as HistoryItems).ItemTitle;
}
}

Resources