reusable datatemplate binding to celltemplate - wpf

I have the following datagrid
<DataGrid x:Name="dataGrid1"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
<DataGrid.Resources>
<DataTemplate DataType="{x:Type DataTypes:Foo}" x:Key="dTemp">
<TextBox Background="{Binding BgColor}" Text="{Binding Path=RowId}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type DataTypes:Foo}" x:Key="dTemp2">
<TextBox Background="{Binding BgColor}" Text="{Binding Path=Alias}"/>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn CellTemplate="{StaticResource dTemp}"/>
<DataGridTemplateColumn CellTemplate="{StaticResource dTemp2}"/>
</DataGrid.Columns>
</DataGrid>
and in the codebehind I have:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public ObservableCollection<Foo[]> ObservableCollection;
public MainWindow()
{
InitializeComponent();
this.ObservableCollection = new ObservableCollection<Foo[]>();
Foo[] ocoll = new Foo[3];
ocoll[0] = (new Foo(1, "FIRST ARRAY FIRST ROW FIRST COLUMN", Brushes.Aqua));
ocoll[1] = (new Foo(2, "FIRST ARRAY FIRST ROW SECOND COLUMN", Brushes.Red));
ocoll[2] = (new Foo(3, "FIRST ARRAY FIRST ROW THIRD COLUMN", Brushes.Green));
Foo[] ocoll2 = new Foo[3];
ocoll2[0] = (new Foo(4, "SECOND ARRAY SECOND ROW FIRST COLUMN", Brushes.Aqua));
ocoll2[1] = (new Foo(5, "SECOND ARRAY SECOND ROW SECOND COLUMN", Brushes.Red));
ocoll2[2] = (new Foo(6, "SECOND ARRAY SECOND ROW THIRD COLUMN", Brushes.Green));
this.ObservableCollection.Add(ocoll);
this.ObservableCollection.Add(ocoll2);
dataGrid1.DataContext = ObservableCollection;
}
}
public class Foo
{
public int RowId { get; set; }
public string Alias { get; set; }
public Brush BgColor { get; set; }
public Foo(int rowId, string #alias, Brush bgColor)
{
this.RowId = rowId;
this.Alias = alias;
this.BgColor = bgColor;
}
}
}
The Object Foo has more than 30 properties (I only wrote 2 in here to make it easier to follow)..
the question is:
do I really have to define 30 different datatemplates (like dTemp, dTemp2, ... see above) to bind the CellTemplate of each DataGridTemplateColumn to it ?

You can create just one implicit DataTemplate for your data type if you do not declare an x:Key value for it:
<DataTemplate DataType="{x:Type DataTypes:YourDataType}">
<TextBox Text="{Binding TextDescription}" Background="{Binding Color}" />
</DataTemplate>
This will automatically be applied to all of your instances of your data type that are within the scope of this DataTemplate, eg. put it in your control Resources or Application.Resources section.
UPDATE >>>
Unfortunately, you still don't seem to have it right. If you re-read my original answer, you should see that I specified that you do not declare an x:Key value for the DataTemplate.
Furthermore, you previously said that all of the DataTemplates would be the same, but now you have added two different ones, so this method will no longer work.
UPDATE 2 >>>
MSDN states that 'A DataTemplate describes the visual structure of a data object'. It might be clearer if it said that a DataTemplate can show the properties of one type of data object. However, only one DataTemplate is required to be defined per object type if you do not declare an x:Key value for it. So if you define one for a particular type, all instances of that type will be automatically rendered according to that DataTemplate.
You asked me 'how to set the DataTemplate to display more than one element in it'... if by that you mean 'how to apply the DataTemplate to more than one instance of the defined data type', the answer is simply to not declare an x:Key value for it and do not set the DataGridTemplateColumn.CellTemplate property. Using this method would render each item with the same UI controls, but with the different values from each instance.
However, if you mean 'how to display different instances of the defined data type differently' as is currently shown in your question, then the answer is shown in your question... you would have to explicitly declare each one with a x:Key value and set the DataGridTemplateColumn.CellTemplate property to the named DataTemplate.

Related

Modifying XAML-based DataTemplate in DataTemplateSelector

Is there a way to modify DataTemplate before returning it in DataTemplateSelector?
My DataTemplate is defined in XAML. There is an element in this template that I need to set binding for, but whose binding path will only be decided at run-time. The template looks like this:
<DataTemplate DataType="vm:FormField">
<StackPanel>
<ComboBox ItemsSource="{Binding ValueList.DefaultView}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode=OneWay}" /> <!--This is the problem child-->
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
TextBlock.Text needs to set its binding path to a property that will be supplied by the underlying data item. My DataTemplateSelector uses the following code to assign it the new path:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
//MultiValueTemplate is the above template
var Content = MultiValueTemplate.LoadContent() as StackPanel;
var ComboItemText = (Content.Children[0] as ComboBox).ItemTemplate.LoadContent() as TextBlock;
//Underlying item contains the field name that I want this to bind to.
ComboItemText.SetBinding(TextBlock.TextProperty, (item as MyItemVM).FieldName);
return MultiValueTemplate;
}
This doesn't work. Code runs, but the output doesn't set TextProperty binding. What do I need to change/add?
Note: I have solved this problem using FrameworkElementFactory approach, but I have had to redefine the entire DataTemplate in the code (which is a pain even for simple template like the one above). I want to use the one that I have already defined in XAML.
Note 2: FrameworkElementFactory approach assigns the constructed template object to DataTemplate.VisualTree in the last step, just before returning. I think it is that part that I'm missing, but there is no way of doing that since VisualTree asks for an object of FrameworkElementFactory type, which we do not have when using XAML-based template.
Background
We are basically getting JSON structure from the server-side that looks something like this:
`[
"Person":
{
"Name": "Peter",
"Score": 53000
},
"Person":
{
"Name": "dotNET",
"Score": 24000
}
,...
]
What fields will be included in JSON will be determined by the server. Our application is required to parse this JSON and then display as many ComboBoxes as there are fields. Each ComboBox will then list down one field in it. So in the above example, there will be one combo for Names and one for Scores. User can choose an option either from the first or second ComboBox, but selecting from one combo will automatically select corresponding item from the other combo(s).
Now you may ask, who the hell designed this idiotic UI? Unfortunately we neither know nor control this decision. I ask the client to instead use ONE Combo (instead of many) with a DataGrid as its dropdown, so that we could display one data item per grid row and user could choose one of those items. Clear and Simple. But the management didn't agree and here we are trying to mimic synchronized comboboxes. LOL.
So what we're currently doing is to transform incoming JSON to a DataTable on-the-fly. This DataTable gets one column for each JSON field and as many row as their are items; kind of pivoting you can say. We then create ComboBoes and bind each one to a single field of this DataTable. This field name is of course dynamic and is decided at run-time, which mean that I have to modify the DataTemplate at run-time, which brings up this question.
Hope it didn't get too boring! :)
look like you can bind SelectedValuePath and DisplayMemberPath to FieldName and be done with that:
<ComboBox SelectedValuePath="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.FieldName}"
DisplayMemberPath="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.FieldName}"/>
Note: For future readers, as mentioned by #ASh in his answer, DisplayMemberPath is a DependencyProperty and can be used to bind to a dynamic field name. This solution in this answer would be over-engineering for this particular problem. I'll still keep it here as it can be useful in certain other scenarios where Binding might not be enough.
Figured it out and was easier than I thought. Instead of modifying the template in DataTemplateSelector, I'm now using a Behavior to modify binding path at runtime. Here is the Behavior:
public class DynamicBindingPathBehavior : Behavior<TextBlock>
{
public string BindingPath
{
get { return (string)GetValue(BindingPathProperty); }
set { SetValue(BindingPathProperty, value); }
}
public static readonly DependencyProperty BindingPathProperty =
DependencyProperty.Register("BindingPath", typeof(string), typeof(DynamicBindingPathBehavior),
new FrameworkPropertyMetadata(null, (sender, e) =>
{
var Behavior = (sender as DynamicBindingPathBehavior);
Behavior.AssociatedObject.SetBinding(TextBlock.TextProperty, new Binding(Behavior.BindingPath));
}));
}
And here is the modification that I had to make in my XAML template:
<DataTemplate DataType="vm:FormField">
<StackPanel>
<ComboBox ItemsSource="{Binding ValueList.DefaultView}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode=OneWay}">
<e:Interaction.Behaviors>
<local:DynamicBindingPathBehavior BindingPath="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.FieldName, Mode=OneWay}" />
</e:Interaction.Behaviors>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
All works well from this point forward.
The other approach is to create your template programmatically in your DataTemplateSelector. If you want to go down that route, here is a rough sketch of how to do it in SelectTemplate function:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var DT = new DataTemplate();
FrameworkElementFactory stackpanelElement = new FrameworkElementFactory(typeof(StackPanel), "stackpanel");
FrameworkElementFactory comboboxElement = new FrameworkElementFactory(typeof(ComboBox), "combobox");
comboboxElement.SetBinding(ComboBox.ItemsSourceProperty, new Binding() { Path = new PropertyPath("ValueList.DefaultView") });
comboboxElement.SetBinding(ComboBox.SelectedItemProperty, new Binding() { Path = new PropertyPath("Value") });
var ItemTemplate = new DataTemplate();
FrameworkElementFactory textblockElement2 = new FrameworkElementFactory(typeof(TextBlock), "textblock2");
textblockElement2.SetBinding(TextBlock.TextProperty, new Binding() { Path = new PropertyPath(YOUR_BINDING_PROPERTY_PATH) });
ItemTemplate.VisualTree = textblockElement2;
comboboxElement.SetValue(ComboBox.ItemTemplateProperty, ItemTemplate);
stackpanelElement.AppendChild(comboboxElement);
DT.VisualTree = stackpanelElement;
return MultiValueTemplate;
}

WPF - How to implement DataTemplate with complex logic?

I am currently transferring my app from WinForms to WPF.
Since I'm new in WPF, I stucked at creating DataTemplates for my treeView items. The screenshot shows how my treeview looked in WinForms version, and I need to get close result in WPF.
(My WinForms treeview)
As you can see, my DataTemplate's logic should take into account these factors:
Node type / defines which icon and fields combination will be displayed for particular item (node). App has about 7-8 node types. Type stored in separate node's field.
Variable values / I need to replace with text if null, etc
Numeric variable values / e.g.: set gray color if zero, etc.
Other properties / e.g.: adding textblocks depending on boolean fields.
And so on...
All these factors result into huge amount of possible item params combinations.
Also I'm using DevComponents WPF DotNetBar AdvTree to divide item properties into columns. I presume I should create 'sub templates' for different field sets and compose from them the entire DataTemplate for each column.
I've learned about triggers, and have to say that implementing my logic with triggers will make my subtemplates huge anyway.
(Current state of my WPF treeview)
So here are my questions:
Are there any ways to dynamically compose complex templates with C# code (without creating raw XAML and loading it at runtime)?
Maybe I should use completely different way (instead of using DataTemplate)? In Winforms I just used OwnerDraw mode, so the task was MUCH easier than in WPF :(
And how to display nested properties inside template? e.g.: Item.Prop.Subprop1.Subprop2.Targetprop.
PS: English is not my first language, sorry for your eyes.
1) The answer is yes.
For exemple if you want to define a template in your window for a simple string
public MainWindow()
{
InitializeComponent();
DataTemplate template = new DataTemplate(typeof(string));
FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border));
borderFactory.SetValue(Border.PaddingProperty, new Thickness(1));
borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1));
borderFactory.SetValue(Border.BorderBrushProperty, Brushes.Red);
FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock));
textFactory.SetBinding(TextBlock.TextProperty, new Binding
{
Mode = BindingMode.OneWay
});
borderFactory.AppendChild(textFactory);
template.VisualTree = borderFactory;
myControl.ContentTemplate = template;
}
And in the Window you just put something like
<ContentControl x:Name="myControl" Content="Test text" Margin="10"/>
Your content control will render the string surrounded by a red border.
But as you anc see it is really complex to define your templates in this way.
The only scenario where i could imagine this approache is for some kind of procedurally generated templates.
Another way is to generate a string for the template and then load it with XamlReader:
string xaml = "<Ellipse Name=\"EllipseAdded\" Width=\"300.5\" Height=\"200\"
Fill=\"Red\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>";
object ellipse = XamlReader.Load(xaml);
2) I don't really see the need to generate templates in code behind. For exemple for this kind of data structure:
public class User
{
public string Name { get; set; }
public User Friend { get; set; }
}
public class RootNode
{
public string Title { get; set; }
public User User { get; set; }
public List<Node> Nodes { get; set; }
}
public class Node
{
public string Title { get; set; }
public List<SubNode> SubNodes { get; set; }
}
public class SubNode
{
public string Title { get; set; }
}
You can define this type of template:
<Window
...
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:RootNode}" ItemsSource="{Binding Nodes}">
<StackPanel x:Name="spContainer" Orientation="Horizontal">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding User.Friend.Friend.Name}"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding User}" Value="{x:Null}">
<Setter TargetName="spContainer" Property="Background" Value="Yellow"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding SubNodes}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:SubNode}" ItemsSource="{Binding Nodes}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding RootNodes}"/>
</Grid>
</Window>
As you can see you can define a template by data type, you can also use triggers to modify the behavior in specific cases, you could also use som binding converters...
3) You can bind to nested properties just like to normal ones :
<TextBlock Text="{Binding User.Friend.Friend.Name}"/>
However in some cases more than two level bindings could fail (fail to resolve or fail to update when property changes, ...)

Using a variable in XAML binding expression

I'm building a control that can edit POCOs. There is a descriptor collection for the fields within the POCO that need to be edited and I'm binding a ListBox's ItemsSource to this collection. Amongst other things, the descriptor gives me the ability to select a suitable DataTemplate and the variable name in the POCO that this ListBox item should edit.
My ListBox is built like this:
<ListBox ItemsSource="{Binding ColumnCollection, ElementName=root}">
<ListBox.Resources>
<DataTemplate x:Key="TextTemplate">
<StackPanel>
<TextBlock Text="{Binding DisplayName}" />
<!-- !!! Question about following line !!! -->
<TextBox Text="{Binding ElementName=vm.CurentEditing, Path=PathName}" />
</StackPanel>
</DataTemplate>
<!-- Details omitted for brevity -->
<DataTemplate x:Key="PickListTemplate" />
<DataTemplate x:Key="BooleanTemplate" />
</ListBox.Resources>
<ListBox.ItemTemplateSelector>
<local:DataTypeSelector
TextTemplate="{StaticResource TextTemplate}"
PickListTemplate="{StaticResource PickListTemplate}"
BooleanTemplate="{StaticResource BooleanTemplate}"
/>
</ListBox.ItemTemplateSelector>
</ListBox>
It is the TextBox binding expression in the "TextTemplate" that I am having problems with. The problem is that "PathName" should not be taken as a literal string, but is the name of a string property in the ColumnDescription class (the collection type of ColumnCollection used for ListBox.ItemsSource), which gives the name of the POCO property I want to bind to (the POCO is "vm.CurrentEditing").
Is there some way to use the value of a property in XAML as input to a binding expression, or will I have to resort to code behind?
(Incidentally, specifying the ElementName as "x.y" as I have done above also seems to be invalid. I assume the "y" part should be in Path but that's currently taken up with my property name...!)
So you want to bind TextBox.Text to Property X of Object Y, where X and Y both change at runtime.
It sounds like what you want to do is something analogous to ListBox.DisplayMemberPath: You can bind a string or PropertyPath property to DisplayMemberPath and it'll work. The way I've done stuff like that is to have a dependency property of type String or PropertyPath, and programatically create a binding from that to whatever property.
So, I wrote an attached property which creates a binding.
public class POCOWrangler
{
#region POCOWrangler.BindPropertyToText Attached Property
public static String GetBindPropertyToText(TextBox obj)
{
return (String)obj.GetValue(BindPropertyToTextProperty);
}
public static void SetBindPropertyToText(TextBox obj, PropertyPath value)
{
obj.SetValue(BindPropertyToTextProperty, value);
}
public static readonly DependencyProperty BindPropertyToTextProperty =
DependencyProperty.RegisterAttached("BindPropertyToText", typeof(String), typeof(POCOWrangler),
new PropertyMetadata(null, BindPropertyToText_PropertyChanged));
private static void BindPropertyToText_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is String && d is TextBox)
{
var tb = d as TextBox;
var binding = new Binding((String)e.NewValue);
// The POCO object we're editing must be the DataContext of the TextBox,
// which is what you've got already -- but don't set Source explicitly
// here. Leave it alone and Binding.Source will be updated as
// TextBox.DataContext changes. If you set it explicitly here, it's
// carved in stone. That's especially a problem if this attached
// property gets initialized before DataContext.
//binding.Source = tb.DataContext;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(tb, TextBox.TextProperty, binding);
}
}
#endregion POCOWrangler.BindPropertyToText Attached Property
}
And I wrote a quick example thing: There's a little class named Foo that has a Name property, and a viewmodel with two properties, Foo Foo and String DisplayPathName. It works! Of course, this depends on default TextBox editing behavior for whatever type the property happens to be. I think that will get you the same results as if you'd bound explicitly in XAML, but it sitll won't always necessarily be just what you want. But you could very easily go a little nuts and add some triggers in the DataTemplate to swap in different editors, or write a DataTemplateSelector.
I stuffed ViewModel.Foo in a ContentControl just to get a DataTemplate into the act, so that the TextBox gets his DataContext in the same manner as yours.
Note also that I'm getting DisplayPathName by a relative source from something outside the DataContext object -- it's not a member of Foo, of course, it's a member of the viewmodel.
C#
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel {
DisplayPathName = "Name",
Foo = new Foo { Name = "Aloysius" }
};
}
XAML
<ContentControl
Content="{Binding Foo}"
>
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBox
local:POCOWrangler.BindPropertyToText="{Binding
DataContext.DisplayPathName,
RelativeSource={RelativeSource AncestorType=ContentControl}}"
/>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
That was fun.

cannot find Name of DataGridColumn programmatically

I found the Columns collection in my datagrid, and was hoping to iterate through it to find a certain column Name. However, I can't figure out how to address the x:Name attribute of the column. This xaml illustrates my problem with a DataGridTextColumn and a DataGridTemplateColumn:
<t:DataGrid x:Name="dgEmployees" ItemsSource="{Binding Employees}"
AutoGenerateColumns="false" Height="300" >
<t:DataGrid.Columns>
<t:DataGridTextColumn x:Name="FirstName" Header="FirstName"
Binding="{Binding FirstName}" />
<t:DataGridTemplateColumn x:Name="LastName" Header="LastName" >
<t:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}" />
</DataTemplate>
</t:DataGridTemplateColumn.CellTemplate>
</t:DataGridTemplateColumn>
</t:DataGrid.Columns>
</t:DataGrid>
And here is my code:
DataGrid dg = this.dgEmployees;
foreach (var column in dg.Columns)
{
System.Console.WriteLine("name: " + (string)column.GetValue(NameProperty));
}
At runtime, no value is present; column.GetValue doesn't return anything. Using Snoop, I confirmed that there is no Name property on either DataGridTextColumn or DataGridTemplateColumn.
What am I missing?
WPF has two different, yet similar concepts, x:Name, which is used to create a field which references an element defined in XAML, i.e. connecting your code-behind to your XAML, and FrameworkElement.Name, which uniquely names an element within a namescope.
If an element has a FrameworkElement.Name property, x:Name will set this property to the value given in XAML. However, there are instances where it is useful to link non FrameworkElement elements to fields in code-behind, such as in your example.
See this related question:
In WPF, what are the differences between the x:Name and Name attributes?
As an alternative, you could define your own attached property which can be used to name the columns. The attached property is defined as follows:
public class DataGridUtil
{
public static string GetName(DependencyObject obj)
{
return (string)obj.GetValue(NameProperty);
}
public static void SetName(DependencyObject obj, string value)
{
obj.SetValue(NameProperty, value);
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.RegisterAttached("Name", typeof(string), typeof(DataGridUtil), new UIPropertyMetadata(""));
}
You can then assign a name to each column ...
xmlns:util="clr-namespace:WPFDataGridExamples"
<t:DataGrid x:Name="dgEmployees" ItemsSource="{Binding Employees}"
AutoGenerateColumns="false" Height="300" >
<t:DataGrid.Columns>
<t:DataGridTextColumn util:DataGridUtil.Name="FirstName" Header="FirstName"
Binding="{Binding FirstName}" />
<t:DataGridTemplateColumn util:DataGridUtil.Name="LastName" Header="LastName" >
<t:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}" />
</DataTemplate>
</t:DataGridTemplateColumn.CellTemplate>
</t:DataGridTemplateColumn>
</t:DataGrid.Columns>
</t:DataGrid>
Then access this name in code as follows:
DataGrid dg = this.dgEmployees;
foreach (var column in dg.Columns)
{
System.Console.WriteLine("name: " + DataGridUtil.GetName(column));
}
Hope that helps
You can use linq query to find name of the datagrid column Headers
dgvReports.Columns.Select(a=>a.Header.ToString()).ToList()
where dgvReports is name of the datagrid.

How to bind a property in itemtemplate to a proptery in itemsource?

Consider this container:
public class ItemInfo : DependencyObject
{
public string Name { get; set; }
public ObservableCollection<SomeDataItem> DataValues { get; set; }
...
Dependency object registration and event handling
...
}
public class MyItemSource : ObservableCollection<ItemInfo>
{
...
}
Now, I wish to display this data in a listview where the control that displays the item is custom. For that, I'd set the MyItemSource to listview's ItemSource and define a ItemTemplate. However, it seems that I have no access to ItemInfo in the ItemTemplate. This is my XAML:
<Grid>
<ListBox ItemsSource="{StaticResource MyStaticDataSource}"
Grid.IsSharedSizeScope="True">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ItemInfoUserControl x:Name="itemInfoUserControl"
Name = "{Binding Name}" <--- this doesn't work
Data = "{Binding DataValues}" <--- this doesn't work
Width="300" Height="200"
Grid.Row="1">
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Instead of binding to ItemSource's ItemInfo, it binds to the ItemInfoUserControl properties, which is not what I wish it to do. Is there a way to bind properties in itemtemplate to a property in itemsource ? Or is there an alternative approach to what i'm ultimately trying to accomplish ?
Thanks!
Well, first of all you need to use proper binding syntax:
Name = "{Binding Name}"
and
Data = "{Binding DataValues}"
Instead of just "Name = "Binding Name"" and "Data = "Binding DataValues"". Note the addition of "{" and "}" around your binding expression.
This might be enough to solve your problem, as long as Name and DataValues are DependencyProperties in ItemInfoUserControl. If not, you'll need to implement them as DependencyProperties in order to be able to bind to them in XAML. See here for a good MSDN article on defining custom dependency properties.
Edit: Also, just noticed -- you're setting both x:Name and Name. From this article on MSDN:
If Name is available as a property on the class, Name and x:Name can be used interchangeably as attributes, but a parse exception will result if both are specified on the same element. If the XAML is markup compiled, the exception will occur on the markup compile, otherwise it occurs on load.
Remove x:Name="itemInfoUserControl" and see if that helps.

Resources