Hi,
i followed your post to write a custom cell presenter control:
<igDP:XamDataGrid Name="DataGrid" > <igDP:XamDataGrid.Resources> <Style x:Key="CellStyle" TargetType="{x:Type igDP:CellValuePresenter}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}"> <StackPanel Orientation="Horizontal"> <!--<Label Content="{TemplateBinding DataContext}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"></Label>--> <my:CWpfIgZelleGui DataContext="{TemplateBinding DataContext}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" /> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </igDP:XamDataGrid.Resources> </igDP:XamDataGrid>
In the code i set the style and my cell control is displayed.
But the problem is with the datacontext:
The datacontext contains the DataRecord. How should i figure out, which cell to display?
Ok, i made a workouround:
[1] I added a DependencyProperty 'Field' to CWpfIgCellGui-control
' [2] I created a celltemplate in the codebehind for each Cell
' [3] in the template i assigned the field to the property
[4] in CWpfIgCellGui i added another datacontext which i set to the cell which i can determine by evaluating [5] the datacontext for the control (which points to datarecord) and the field from my own dependency property.
that is quite sophisticated to realize a standard usecase (and i guess displaying a cell value in a cellvaluepresenter should be a standard use case) so i hope there is a better solution. (The solution for my understanding would be that the data context contains the cell, not the record)
here's the code:
' [1] I added a DependencyProperty 'Field' to CWpfIgCellGui-control
Public Shared ReadOnly FieldProperty As DependencyProperty = DependencyProperty.Register("Field", GetType(Field), GetType(CWpfIgZelleGui), New PropertyMetadata(AddressOf FieldChanged)) Public Property Field() As Field Get Return DirectCast(Me.GetValue(FieldProperty), Field) End Get Set(ByVal value As Field) Me.SetValue(FieldProperty, value) End Set End Property
Dim aField As New UnboundField Dim aCellStyle As New Style aCellStyle.TargetType = GetType(CellValuePresenter) Dim aTemplateSetter As New Setter aTemplateSetter.Property = CellValuePresenter.TemplateProperty Dim aTemplate As New ControlTemplate(GetType(CellValuePresenter)) Dim aTemplateElementFactory As New FrameworkElementFactory(GetType(CWpfIgZelleGui)) aTemplateElementFactory.SetValue(CWpfIgZelleGui.FieldProperty, aField) ' ' [3] in the template i assigned the field to the property aTemplate.VisualTree = aTemplateElementFactory aTemplate.Seal() aTemplateSetter.Value = aTemplate aCellStyle.Setters.Add(aTemplateSetter) aField.Settings.CellValuePresenterStyle = aCellStyle aField.Name = Me.UnboundFieldName aField.DataType = GetType(Integer)
' [4]
Private Sub CWpfIgZelleGui_DataContextChanged(ByVal sender As Object, ByVal e As System.Windows.DependencyPropertyChangedEventArgs) Handles Me.DataContextChanged Me.GridDataContextFüllen() End Sub Private Shared Sub FieldChanged(ByVal d As System.Windows.DependencyObject, ByVal e As System.Windows.DependencyPropertyChangedEventArgs) DirectCast(d, CWpfIgZelleGui).GridDataContextFüllen() End Sub
Private Sub GridDataContextFüllen() Dim aField As Field = Me.Field Dim aRecord As DataRecord = DirectCast(Me.DataContext, DataRecord) Dim aCell As Cell If aRecord IsNot Nothing And aField IsNot Nothing Then aCell = aRecord.Cells(aField) ' [5] evaluating the cell which we need to display the cell value. Else aCell = Nothing End If Me.GridM.DataContext = aCell End Sub
Hello,
Probably there is a simpler solution, but I was not able to fully understand your question :
"How should i figure out, which cell to display?"
Yes, the DataContext is the DataRecord. If you are trying to figure our which field uses the specific CellValuePresenter, then you can bind to the Field property of the CVP ( use TemplateBinding Path=Field) or use a RelativeSource - TemplatedParent, Path=Field.
You wrote:
> I was not able to fully understand your question : "How should i figure out, which cell to display?"
Well, i'm using the datacontext always to transport the viewmodel for the control, i guess that's it's intention.
So the viewmodel for a control which displays a cell would be the cell, not the record. I'd expect the record as a datacontext only in a RowControl- if there is any.
That's why i got a bit confused. Because when i want to display a cell i was expecting the cell as a datacontext. But when i retrieve the record i need to aditionally figure out which cell to display. We have several solutions to do so but i guess the most simple would be to obtain cell in the datacontext.
It sounds like you need to bind to the Value property of the CellValuePreseenter. It will give you the value of that cell - the object that this cell is bound to. Have you tried it?
I have the same question and I don't think it was answered above. The problem is that when you create a style that has a TargetType of CellValuePressenter, there is no way (inside the Style) to determine which Cell or Field the Style is applied to. The reason for this is that the item that the style is applied to is a Record. That is non-intuitive and has often been very inconvenient - frankly, it has been so inconvenient so frequently that I'm shopping around for other WPF grid controls. It would be better if the style were applied to a Cell instead. Then, you could do things like use Field properties in the triggers for the CellValuePresenter style (which is what I'm currently trying to do).
If the item that the CellValuePresenterStyle is applied to were a Cell instead of a Record, the code below would work. If they need it, people could still get the Record using Cell.Record. The local:FieldExtensions.ExampleFlag is a custom attached property. This is just an example to help describe the type of thing I need to do. Yes, I might be able to do this sort of thing on a field-by-field basis but that leads to overly complicated, hard to understand, and difficult to maintain code - all of which are reason why I like to use the 3rd party components that Infragistics sells.
<Style TargetType="{x:Type igDP:CellValuePresenter}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Field.(local:FieldExtensions.ExampleFlag), RelativeSource={RelativeSource self}}" Value="True">
<Setter Property="ToolTip" Value="It works!!!"/>
</DataTrigger>
</Style.Triggers>
</Style>
Karle,
I am glad you have worked this out, and thanks for sharing the solution, in case someone else encounters the same issue.
Alex,
It is working now. Thanks for your tips.
I use Cell.Value to store a system.string to keep the sorting and grouping. In cell.tag i store a viewmodel which also contains the application context. I need this context to work. This is why i need the cell object: To obtain cell.tag.
i succeeded by writing a custom dependency property called 'field'. I bind this to the cellvaluepresenters field property. With this field and with the record i receive from the datacontext i can determine the cell object i need.
Karle