ValueConverter not invoked in DataTemplate binding - wpf

I have a ComboBox that uses a DataTemplate. The DataTemplate contains a binding which uses an IValueConverter to convert an enumerated value into a string. The problem is that the value converter is never invoked. If I put a breakpoint in StatusToTextConverter.Convert(), it never is hit.
This is my XAML:
<ComboBox ItemsSource="{Binding Path=StatusChoices, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource StatusToTextConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I thought this is how one implicitly binds to the value a DataTemplate is presenting. Am I wrong?
Edit: For context: I intend to display an Image in the DataTemplate alongside that TextBox. If I can't get the TextBox binding to work, then I don't think the Image will work, either.

In some circumstances you must explicitly supply a Path for a Binding. Try this instead:
<TextBlock Text="{Binding Path=.,Converter={StaticResource StatusToTextConverter}}"/>

Related

TextBox ConvertBack event doesn't fire for XML element

ValueFormattingConverter.Convert is called with the XmlElement. ConvertBack is never called. Why? Is there some obligation to pass binding directives down the chain? Is the use of the TextBox overriding its own binding settings? What can be done?
My TextBox
<TextBox Width="200"
Text="{Binding Path=., Converter={StaticResource valueFormattingConverter}}",
Mode=TwoWay,
NotifyOnSourceUpdated=True,
NotifyOnValidationError=True,
UpdateSourceTrigger=PropertyChanged}" />
Usage is rather convoluted. Starting at the top, we provide an XML element to a tab.
<TabItem.DataContext>
<Binding Source="{StaticResource mcf}",
XPath="mdf/press_information"/>
</TabItem.DataContext>
That tab contains a ItemsControl which builds TextBoxes through this ControlChooser which passes the binding along.
<ItemsControl.ItemTemplate>
<DataTemplate>
<W3V:ControlChooser RelativeSource="{RelativeSource AncestorType=W3V:ObjectList}",
Content="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
My converter class header. Convert method is called. ConvertBack never.
[ValueConversion(typeof(XmlElement), typeof(string))]
public class ValueFormattingConverter : IValueConverter
EDIT: The chosen answer basically says Path=. doesn't support 2-way binding. I believe it is the correct answer to the question. Very helpful to know, but "can't do that" doesn't solve the larger problem. So I have laid out the larger question here: Means of generating an editable form from XML.
The binding direction to source won't work with a {Binding Path=.}. This is because there is no bound property, but just the binding source object.
Hence there will never be a source update, and the ConvertBack method is never called, because that would mean to replace the source object.
In order to make your code work, you would have to bind to some property:
<TextBox Text="{Binding Path=SomeElement, ...}"/>

WPF Binding - Self Binding with its own DataContext

Anyone got a situation to bind the same DataContext to Text property (for example) in TextBlock.
I have to assign the DataContext to reflect some trigger based on the Data values from Datacontext in my style. at the same time, i need to bind with the same DataContext object to get the Text Property After applying some conversion on either IValueConverter/IMultivalueConverter.
As i know {Binding}, just bind with the current datacontext. But in the same scenario how to use converter with it?
Any suggestions will be appreciated.
<TextBlock Style="{StaticResource DataEntryTextBlock1}" Grid.Row="1"
DataContext="{Binding MyField1}"
Text="{Binding MyField1, Converter={StaticResource myConverter}}">
</TextBlock>
This XAML script does not work, as the Text binding is trying to look for the MyField1 variable inside the MyField1.
Thanks,
Vinodh
{Binding} is equivalent to {Binding Path=.} so in you case you can use
Text="{Binding Path=., Converter={StaticResource myConverter}}"
Binding.Path on MSDN
Optionally, a period (.) path can be used to bind to the current source. For example, Text="{Binding}" is equivalent to Text="{Binding Path=.}"

Two way binding in ListBox ItemTemplate

I have a ListBox which DataTemplate is TextBox that can be edited. Where should I set Binding TwoWay? In ItemSource or In TextBox binding? Maybe in both? And how it works inside? Is it inherited? So if I set Binding in ItemSource - is it inherited in TextBox?
<ListBox HorizontalAlignment="Left" ItemsSource="{Binding Commands, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Two way binding should be setup op your item you need to display, in this case the Textbox. Here you need to have coupling back to your datacontext. You might want to consider setting the UpdateSourceTrigger property to PropertChanged.
This way you will always have entered value of your text, even without loosing focus.
The itemsource should not be Two way. One way will do since you probable will be binding to an observable collection. This will only be set once from your datacontext. This will automatically handle the adding and removing of items to your collection.
I'd add your code like this:
<ListBox Margin="10,0,0,0" Width="200" HorizontalAlignment="Left" ItemsSource="{Binding Commands}" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Where should I set Binding TwoWay?
You should set this Mode for TextBox like this:
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
If I'm not mistaken, the Text property is listed TwoWay mode by default. Therefore, it's construction is not required.
From MSDN:
When used in data-binding scenarios, this property uses the default update behavior of UpdateSourceTrigger.LostFocus.
This means that updates the properties were visible at once, you need to set the property UpdateSourceTrigger to PropertyChanged:
<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
So if I set Binding in ItemSource - is it inherited in TextBox?
No, inheritance will not be, because settings of Binding unique for each dependency property. Inheritance happens when using DataContext, but again, settings unique for each property.

ListBox Bound to SortedSet. How To Bind TextBox?

The ItemsSource (SsString) is a SortedSet string
I want to use a TextBox (not the default TextBlock) in a ListBox but I cannot figure out how to bind to the value in the SortSet.
I have tried binding with no path, Key, key, Value, and value.
<ListBox ItemsSource="{Binding Path=SsString}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Key}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The following works but it displays TextBlock.
<ListBox ItemsSource="{Binding Path=SsString}" />
You won't be able to edit the bound values. You need a class as the item so you can target a property with the Binding.Path.
(You should be able to bind this using {Binding .}, but it's one-way)

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.)

Resources