Reputation: 388
In my project I have a list of Units
which is being used as the source of data for a DataGrid. The Units
type has two types of subclasses, AUnits
and BUnits
. Each Unit
in the list is either an AUnit
or aBUnit
. My issue is when I try to bind to a property specific to one of the subclass unit types, XAML doesn't see it and I just get back 0's. Normally, if this was being done in C# I would just cast it and access the property, but I am not able to do that at this point in my code. The bindings are being created in C# like this:
dgtc.Header = Properties.Resources.MaxPressure;
dgtc.MinWidth = 25;
dgtc.Width = Properties.Settings.Default.MaxPressureColumnWidth;
dgtc.IsReadOnly = true;
dgtc.Binding = new Binding("Unit.MaxDepthRelativeToEntry")
{
Converter = new DistanceUnitsConverter()
};
Where dgtc is a DataGridTextColumn. Unit.MaxDepthRelativeToEntry comes through as 0 because it is a property on the subclass of an AUnit
, so XAML thinks I am trying to access an non-existent property.
I have read this answer and so far I have tried some of the following syntaxes:
dgtc.Binding = new Binding("AUnit.MaxDepthRelativeToEntry")
dgtc.Binding = new Binding("Unit(MyNameSpace:AUnit).MaxDepthRelativeToEntry")
dgtc.Binding = new Binding("Unit(MyNameSpace:AUnit.MaxDepthRelativeToEntry)")
and was not able to get any of those to work. I have also tried doing this through a converter, but the issue is, I don't have the list of units available to me when I am constructing the DataGrid/ setting up the bindings/etc. so I am not able to grab the property out of the instance and return it. Does anyone know of any way that I can, preferably in XAML, get to the properties of a subclass type of the type I am binding to?
Edit:
My DataGrid has the following XAML:
<DataGrid x:Name="JobListView"
AutoGenerateColumns="False"
ItemsSource="{Binding UnitStatusCollection, Mode=TwoWay}"
CanUserDeleteRows="False"
Style="{StaticResource JobGridViewStyle}"
SelectedItem="{Binding JobsListViewSelectedUnitInfo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Utility:DataGridColumnsBehavior.BindableColumns="{Binding DataGridColumns}"
ContextMenu="{StaticResource ListViewContextMenu}"
Margin="10,5,10,2"
Grid.Row="2"
SelectionMode="Single"
SelectionUnit="FullRow"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
RowStyle="{StaticResource DataGridRowStyle}"
CellStyle="{StaticResource DataGridCellStyle}"
AlternationCount="2"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
CanUserResizeRows="False"
HorizontalGridLinesBrush="#d6d6d6"
VerticalGridLinesBrush="#d6d6d6"
Background="#EAEAEA"
>
The ItemsSource
is set to the UnitStatusCollection
which is an ObservableCollection
of a class called UnitInfo
which holds a Unit
and a UnitStatus
. I need to access the property MaxDepthRelativeToEntry
in Unit
of UnitInfo
. But I need to be able to see Unit
as AUnit
Upvotes: 0
Views: 1687
Reputation: 132548
If you are binding to a list of Unit
objects, then the DataContext
for your DataGridTextColumn
should be the AUnit
or BUnit
object itself, so your binding path should just be new Binding("MaxDepthRelativeToEntry")
.
You might get some kind of runtime warning for properties that only exist on one SubClass but not others, but it shouldn't throw an exception.
Here's a quick code sample to give an example :
XAML :
<DataGrid x:Name="dgTest" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="A" Binding="{Binding A}" />
<DataGridTextColumn Header="B" Binding="{Binding B}" />
<DataGridTextColumn Header="C" Binding="{Binding C}" />
</DataGrid.Columns>
</DataGrid>
Code-Behind :
var test = new List<ClassA>();
test.Add(new ClassB() { A = "A", B = "B" });
test.Add(new ClassC() { A = "A", C = "C" });
dgTest.ItemsSource = test;
where the classes are defined as
public class ClassA
{
public string A { get; set; }
}
public class ClassB : ClassA
{
public string B { get; set; }
}
public class ClassC : ClassA
{
public string C { get; set; }
}
Output :
It also works the exact same way if I write the binding in code-behind instead of in XAML :
colB.Binding = new Binding("B")
Upvotes: 2