Here's how to add a comment indicator to a DataGridCell similar to an Excel functionality using MultiValueConverter. See codefiles and screenshot below.
XAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 | <Window x:Class="WPFExcelCommentIndicator.DataGridCellCommentIndicator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WPFExcelCommentIndicator"
Title="DataGridCellCommentIndicator" Height="350" Width="500" WindowStartupLocation="CenterScreen" >
<Window.Resources>
<src:DataGridCellComment x:Key="DataGridCellComment" />
<src:StudentList x:Key="StudentListData" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="225"/>
<RowDefinition Height="50"/>
<RowDefinition Height="225"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" AutoGenerateColumns="False" CanUserResizeColumns="True"
CanUserAddRows="False" SelectionMode="Single" SelectionUnit="Cell" ItemsSource ="{Binding Path=StudentItems}"
Name="dgStudents">
<DataGrid.Resources>
<DataTemplate x:Key="DateTemplate">
<Canvas x:Name="pnlContainer" Height="25">
<TextBlock x:Name="txtAge" IsEnabled="False" Foreground="Green" Text="{Binding Path=Age, Mode=TwoWay}" />
<Polygon IsEnabled="False" ClipToBounds="False" VerticalAlignment="Top" x:Name="polyExcel">
<Polygon.Fill>
<SolidColorBrush Color="Red" />
</Polygon.Fill>
<Polygon.Points>
<MultiBinding Converter="{StaticResource DataGridCellComment}">
<Binding RelativeSource="{RelativeSource Mode=Self}"/>
<Binding Path="Age"></Binding>
</MultiBinding>
</Polygon.Points>
</Polygon>
</Canvas>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<EventSetter Event="PreviewMouseDown" Handler="CheckPolygon"/>
<EventSetter Event="SizeChanged" Handler="Cell_SizedChanged" />
</Style>
</DataGrid.CellStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" Width="100" IsReadOnly="True" />
<DataGridTemplateColumn Header="Age" CellTemplate="{StaticResource DateTemplate}" Width="100" >
</DataGridTemplateColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" Width="100" IsReadOnly="True" />
<DataGridTextColumn Header="Address" Binding="{Binding Path=Address}" Width="*" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
|
Code Behind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | public partial class DataGridCellCommentIndicator : Window
{
public DataGridCellCommentIndicator()
{
InitializeComponent();
this.DataContext = this;
}
public StudentList StudentItems
{
get { return new StudentList(); }
}
void CheckPolygon(object sender, RoutedEventArgs e)
{
}
private void Cell_SizedChanged(object sender, SizeChangedEventArgs e)
{
DataGridCell cell = (DataGridCell)sender;
if (cell.Column.Header.ToString().Equals("Age"))
{
Polygon poly = ControlExtensions.GetVisualChild<Polygon>(cell);
TextBlock textAge = ControlExtensions.GetVisualChild<TextBlock>(cell);
if (cell.ActualWidth != 100 && Convert.ToInt32(textAge.Text) >= 30)
{
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(new Point(cell.ActualWidth - 13, cell.ActualHeight - (cell.ActualHeight + 1)));
myPointCollection.Add(new Point(cell.ActualWidth - 2, cell.ActualHeight - (cell.ActualHeight + 1)));
myPointCollection.Add(new Point(cell.ActualWidth - 2, cell.ActualHeight - 20));
poly.Points = myPointCollection;
}
}
}
}
|
DataGridCell Comment Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | public class DataGridCellComment : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
DataGridCell cell = ((Polygon)values[0]).GetAncestor<DataGridCell>();
TextBlock textAge = ControlExtensions.GetVisualChild<TextBlock>(cell);
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(new Point(cell.ActualWidth - 13, cell.ActualHeight - (cell.ActualHeight + 1)));
myPointCollection.Add(new Point(cell.ActualWidth - 2, cell.ActualHeight - (cell.ActualHeight + 1)));
myPointCollection.Add(new Point(cell.ActualWidth - 2, cell.ActualHeight - 20));
if (System.Convert.ToInt32(textAge.Text) >= 30)
{
return myPointCollection;
}
else
{
return null;
}
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
|
Control Extension Method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | public static T GetVisualChild<T>(Visual parent)
where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>
(v);
}
if (child != null)
{
break;
}
}
return child;
}
|
StudentList and Student Classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | public class StudentList : ObservableCollection<Student>
{
public StudentList()
{
Add(new Student { ID = 1, Age = 29, Name = "Mike", Address = "Cebu" });
Add(new Student { ID = 2, Age = 28, Name = "Phil", Address = "Cebu" });
Add(new Student { ID = 3, Age = 23, Name = "Chelsy", Address = "Leyte" });
Add(new Student { ID = 4, Age = 33, Name = "Jeff", Address = "Leyte" });
Add(new Student { ID = 5, Age = 32, Name = "Greg", Address = "Cebu" });
Add(new Student { ID = 6, Age = 28, Name = "Howard", Address = "Bohol" });
Add(new Student { ID = 7, Age = 27, Name = "Grant", Address = "Bohol" });
}
}
public class Student
{
public int ID { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
|
Screenshot
Comments
Post a Comment