Dynamic Telerik RadOutlookBar headers come out wrong with ItemTemplate - wpf

I'm trying to use Telerik RadControls in a MVVM kind of way but having some strange problems.
The Viewmodel behind the RadOutlookBar has a collection of ViewModels that each have a Title string property. I wanted to define it so way the they get Wrapped inside a RadOutlookBarItem and bind the header/title properties together.
XAML:
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=Title}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<telerik:RadOutlookBarItem Header="{Binding Path=Title}" >
<ContentControl Content="{Binding}" />
</telerik:RadOutlookBarItem>
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>
This works as intended except that the Header comes out strange. Instead of being like a static string item it seems to get wrapped inside another object that behaves like a similar to a RadOutlookBarItem ( it' changes color when mouseover and such )
Even if I cahnge to straightforward string instead of binding it's still strange. But If I don't define a ItemTemplate inside the RadOutlookBar (that is, not a dynamic control) it looks all right.
What could be going on there?

Solved this and another problem in one fell swoop. I was binding to the wrong Template the whole time. This made me think I had to add OutLookBarItem myself.
In the end I was supposed to bind what I was trying to bind to the ContentTemplate.
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.ContentTemplate>
<DataTemplate >
<ContentControl Content="{Binding}" />
</DataTemplate>
</telerik:RadOutlookBar.ContentTemplate>
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>
Should work I think.

Related

Code behind can`t find element in XAML

I have an element in my XAML called Tasklst which I was able to reference it in my code-behind without a problem. However, when I introduced a tab control (as shown below) and moved my Tasklst inside a DataTemplate, suddenly my code-behind was telling me that Tasklst cannot find it. How do I reference it now?
<dx:DXTabControl x:Name="TabControl"
ItemsSource="{Binding Sequences}"
SelectionChanged="TabControl_OnSelectionChanged"
SelectedItem="">
<dx:DXTabControl.View>
<dx:TabControlMultiLineView HeaderLocation="Bottom" />
</dx:DXTabControl.View>
<!--Header-->
<dx:DXTabControl.ItemHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</dx:DXTabControl.ItemHeaderTemplate>
<!--Content-->
<dx:DXTabControl.ItemTemplate>
<DataTemplate>
<views:DxTaskList x:Name="Tasklst" />
</DataTemplate>
</dx:DXTabControl.ItemTemplate>
</dx:DXTabControl>
DataTemplate is the Problem here ...
you can do something like this
(DxTaskList)TabControl.Template.FindName("Tasklst", TabControl);

Binding ListBox Items using Templates

I am going crazy trying to figure this out without success.
I have a DependencyObject, ("UserObject"). It has a "DataItems" DependecyProperty that is an ObservableCollection. "UserDefiniton" is a DependencyObject with a DependencyProperty of "Data". Data has two properties: DataType (an enumeration) and Value (a string).
I am trying to define a ListBox in XAML that uses the "DataItems" property as its ItemsSource. In the ItemTemplate, I have several different controls. For simplicity of this issue, I am using a CheckBox and a TextBox. I want CheckBox to be available and visible when DataType is 0, while I want the TextBox to be available and visible when the DataType is 1. Only one control can be available and visible at a time.
This works:
<ListBox
ItemsSource={Binding DataItems, Mode=OneWay}>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox
Visibility="{Binding Path=Data.DataType, Mode=OneWay, Converter={StaticResource VisibilityConverter}, ConverterParameter=0}"
IsChecked="{Binding Path=Data.Value, Mode=TwoWay, Converter={StaticResource StringToBoolean}}" />
<TextBox
Visibility="{Binding Path=Data.DataType, Mode=OneWay, Converter={StaticResource VisibilityConverter}, ConverterParameter=1}"
Text="{Binding Path=Data.Value, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
<Listbox.ItemTemplate>
</ListBox>
The problem is that even though only one is visible, both are fighting over the Data.Value property (the boolean of the checkbox will show in the textbox, even though the checkbox is hidden).
Basically, though, the binding in this case is working--but the implementation is incorrect.
So, I switched to using Templates. The problem I am having is that I can't get the binding to work.
This is the code that I have for the Template. The Template selector is working correctly, but the Text property of the TextBox and the IsChecked property of the checkbox are not binding to Data.Value:
<DataTemplate x:Key="TextBoxItem">
<TextBox
Text="{Binding Path=Data.Value, Mode=TwoWay}" />
</DataTemplate>
<DataTemplate x:Key="CheckBoxItem">
<CheckBox
IsChecked="{Binding Path=Data.Value, Mode=TwoWay, Converter={StaticResource StringToBoolean}}" />
</DataTemplate>
...
<ListBox
ItemsSource={Binding DataItems, Mode=OneWay}>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl
Content="{Binding Path=Data.DataType, Mode=OneWay}"
ContentTemplateSelector="{DynamicResource UserDefinitionTemplateSelector}"/>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
So how do I fix the binding?
Content should be set to {Binding}, since the Content will be the DataContext of the data-templates, hence you should just pass on the current DataContext. If you need to pass specific data to the template selector you can just drill down in the whole object.
There also is a template selector on the level of the ListBox, so you do not really need the internal ContentControl.
(You might also be interested in generic methods of debugging data bindings.)

Access property of DataContext inside ItemTemplate

I have a really nasty problem with bindings. I know that there are other topics regarding binding itmes inside itemtemplate to datacontext of an object outside the template. However, this just won't work, i.e. the first textblock display 'Test' as desired whereas the same textbox inside the itemtemplate shows nothing.
<TextBlock Text="{Binding DataContext.Test, ElementName=myList}"/>
<ItemsControl x:Name="myList" ItemsSource="{Binding AllItems}"
Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal"
ItemHeight="170" ItemWidth="140"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image x:Name="{Binding KeyName}"
Source="{Binding ImagePath}"
Width="128"
Height="128">
</Image>
<TextBlock Text="{Binding DataContext.Test, ElementName=myList}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I would appreciate some help here folks as this is really a problem for me.
Inside the itemtemplate, the binding is initialized to the context of the current item in AllItems.
Update
Outside of the ItemTemplateyour bindings are relative to the DataContext of the page.**
Once inside an ItemTemplate then bindings are limited to the scope of the item specifically being evaluated at that time.
So, if we assume the following (based on the code in your question):
<ItemsControl x:Name="myList" ItemsSource="{Binding AllItems}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="tb1"
Text="{Binding DataContext.Test, ElementName=myList}"/>
<TextBlock x:Name="tb2" Text="{Binding KeyName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
tb1 cannot access the DataContext object directly.
tb2 cann access KeyName - assuming that whatever object AllItems is an IEnumerable of contains a property with that name.
As I understand it, inside an itemtemplate, the item past from the enumeration controls the binding source and this can't be overridden (by setting ElementName or otherwise).
If you need the value from Test in every object in your enumeration then you'll need to add it as a property of the object in the enumeration.
I'm sure someone more knowledgeable than me could explain why this is or give a better explanation but that's the gist of it.
** Assuming no other nesting of ItemsControls (or equivalent)

How can I achieve a binding path which is bound by another binding?

I'm writing my own UserControl which displays data in a ListBox. I want to achieve something similar to a property like "DisplayMemberPath". In my example, it's "EditableMemberPath", which should determine which member will be displayed in the textbox. However, using a binding on a binding does not work.
<ListBox ItemsSource="{Binding Path=Items, ElementName=me}"
SelectedItem="{Binding Path=SelectedItem, ElementName=me}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Converter={Binding Path=ItemToImageConverter, ElementName=me}}" />
<TextBlock Text="{Binding Path={Binding Path=EditableMemberPath, ElementName=me}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Can you help me finding a proper solution?
Best Regards
Oliver Hanappi
You can't do that directly in XAML (at least not with the built-in classes) : a Binding is not a DependencyObject, so you can't bind its properties.
However the post mentioned by Martin Harris looks promising...

How can I factor out a DataTemplate's binding in WPF?

I have a DataTemplate I want to reuse. The part I want to factor out is the binding, because it's the only thing that changes. My DataTemplate looks roughly like this. (There's actually quite a bit more to it, but I've taken out the extraneous stuff.)
<DataTemplate>
<TextBox Text="{Binding Name}" />
</DataTemplate>
How can I reuse this DataTemplate while simply varying the property to which I'm binding? (Note that if it were as simple as just a TextBox, I wouldn't worry about it, but the DataTemplate actually contains a StackPanel with a number of other elements in it. I want to centralize that in one place, hence the DataTemplate.)
I've thought about two ways to tackle this problem.
Create a simple custom control. Reuse that, and don't worry about reusing the DataTemplate.
Experiment with some kind of subclass of DataTemplate. (I'm told this is possible.) I'd add a dependency property to it that lets me specify the name of the property to which I want to bind.
Suggestions?
I hate answering my own questions, but for the sake of completeness, here's my solution.
<ListBox ItemsSource="{Binding}">
<ListBox.Resources>
<ControlTemplate x:Key="textBoxControlTemplate" TargetType="ContentControl">
<TextBox Text="{TemplateBinding Content}" />
</ControlTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}" Template="{StaticResource textBoxControlTemplate}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This of course is a very contrived example. In my own app, I'm not actually putting textboxes inside of a listbox. In a listbox, this is not very useful, but imagine it inside of a DataGrid, where each column might be displayed in a similar way, but binds to a different property.
Create a UserControl and use it within the DataTemplate.
<DataTemplate>
<local:MyComplexUserControl DataContext="{Binding Name}"/>
</DataTemplate>
and within the UserControl:
<StackPanel>
<TextBlock>Value:</Text>
<TextBox Text="{Binding}"/>
</StackPanel>
Have a separate DataTemplate with its own binding for each occasion.

Resources