I'm writing an application that is able to switch language using this.
I also have a combox with two features:
supply help text if no item is selected in combobox (see this)
items are selectable with checkboxes (see this)
My combobox looks like
<Grid>
<ComboBox x:Name="MyCB" SelectionChanged="OnCbObjectsSelectionChanged" ...>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" Width="20" />
<TextBlock Text="{Binding Value}" Width="100" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Visibility="{Binding SelectedItem, ElementName=MyCB, Converter={StaticResource Null2Vis}}"
IsHitTestVisible="False"
VerticalAlignment="Center"
Name="tbObjects"
Text="{ns:Loc Var1}"
FontSize="20"
Foreground="Gray"/>
</Grid>
I temporary deactivated the converter with return Visibility.Visible; with no effect.
Whenever I check some checkboxes the combobox.Text property is set and the binding from ns:Loc is overriden. How can I set it again in code if all checkboxes are unchecked?
private void OnCbObjectCheckBoxChecked(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (var cbObject in MyCB.Items)
if (cbObject.IsSelected)
sb.AppendFormat("{0}, ", cbObject.Value);
tbObjects.Text = sb.ToString().Trim().TrimEnd(',');
if (tbObjects.Text == "")
{
Binding myBinding = new Binding();
myBinding.Source = TranslationSource.Instance["Var1"]; // <- this does not work :/
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
}
When all checkboxes are unchecked there is no text in the combobox.
What am I missing?
Edit: Added TextBox element to code
If I understand your code correctly to restore the localization binding you don't need to redefine the Binding - it should be sufficient to use LocExtension with proper argument, because it derives from Binding:
if (tbObjects.Text == "")
{
var myBinding = new LocExtension("Var1");
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
But if for some reason you still want to redefine the Binding, here's what it should look like:
if (tbObjects.Text == "")
{
Binding myBinding = new Binding("[Var1]");
myBinding.Source = TranslationSource.Instance;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
Note that the source for the binding is TranslationSource.Instance, and the path should be "[Var1]" to indicate its indexer with "Var1" argument.
Side note
Since TranslationSource.Item[string] indexer is read-only, setting the Binding.UpdateSourceTrigger is reduntant. Also, for the same reason, I'd set Binding.Mode to OneWay.
Related
I tried to create a TabItem with a TextBox in it from this article.
I found out that the TabItem Header is NOT bind to the TextBox.
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
TabItem ti = new TabItem();
DataTemplate tabItemTemplate = new DataTemplate();
tabItemTemplate.DataType = typeof(TabItem);
FrameworkElementFactory textBoxFactory = new FrameworkElementFactory(typeof(TextBox));
textBoxFactory.SetBinding(TextBox.TextProperty, new Binding("."));
textBoxFactory.SetValue(NameProperty, "textBox");
textBoxFactory.SetValue(BorderThicknessProperty, new Thickness(0));
//textBoxFactory.SetValue(IsEnabledProperty, false);
tabItemTemplate.VisualTree = textBoxFactory;
ti.Header = "Test!";
ti.HeaderTemplate = tabItemTemplate;
ti.MouseDoubleClick += TabItem_MouseDoubleClick;
tabControl.Items.Add(ti);
}
private void TabItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
MessageBox.Show((sender as TabItem).Header.ToString());
}
Could somebody please be so kind and teach me how to bind it correctly?
Much appreciated!
Your Binding configuration is wrong.
new Binding(".") is missing the Binding.Source.
It should be:
var binding = new Binding("Header") { Source = ti };
Example of using XAML
The following example replicates your C# code
<TabControl>
<TabItem Header="Test" MouseDoubleClick="TabItem_MouseDoubleClick" >
<TabItem.HeaderTemplate>
<DataTemplate>
<TextBox x:Name="textBox"
Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=Header}" />
</DataTemplate>
</TabItem.HeaderTemplate>
</TabItem>
</TabControl>
Complementing #BionicCode's answer
The problem with your original binding is that you are pointing to the current Data Context.
Your binding is equivalent to an empty Binding "new Binding ();".
Thus, you get a binding not to a property, but to a source (The default source is the current Data Context).
But the binding can only change the property of the source, not the source itself.
The Header template is applied to the contents of the TabItem's Header property.
Therefore, to get the same value, but not as a source of the binding, but as a property in the Path of the binding, you need to go up to the TabItem level.
#BionicCode in his answer showed you examples of such bindings.
I will offer another option for integration into your code:
private static readonly DataTemplate headerTemplate = (DataTemplate)XamlReader.Parse
(#"
<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<TextBox x:Name='textBox'
Text='{Binding Header,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}},
UpdateSourceTrigger=PropertyChanged}'
BorderThickness='0'/>
</DataTemplate>
");
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
TabItem ti = new TabItem();
ti.Header = "Test!";
ti.HeaderTemplate = headerTemplate;
ti.MouseDoubleClick += TabItem_MouseDoubleClick;
tabControl.Items.Add(ti);
}
I'm trying to apply a data template programatically behind code. I've set the properties fine but I'm stuck on how to add the Click Event. May I ask how abouts do I do that?
Xaml Code that's being copied
<DataTemplate>
<telerik:RadToggleButton Content="+"
Width="20"
Height="20"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Click="RiskButton_OnClick"
Visibility="{Binding AttachmentVisibility, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</DataTemplate>
What I currently have
var toggleButton = new FrameworkElementFactory(typeof(RadToggleButton));
toggleButton.SetValue(RadToggleButton.ContentProperty, "+");
toggleButton.SetValue(RadToggleButton.WidthProperty, 20.0);
toggleButton.SetValue(RadToggleButton.HeightProperty, 20.0);
toggleButton.SetValue(RadToggleButton.HorizontalContentAlignmentProperty, HorizontalAlignment.Center);
toggleButton.SetValue(RadToggleButton.VerticalAlignmentProperty, VerticalAlignment.Center);
//toggleButton.AddHandler(); <- what goes here?
DataTemplate dt = new DataTemplate
{
VisualTree = toggleButton
};
dt.Seal();
toggleButton.AddHandler(RadToggleButton.ClickEvent, new RoutedEventHandler(SomeHandler));
SomeHandler is a RoutedEventHandler:
public void SomeHandler(object sender, RoutedEventArgs e)
{
}
I have to bind dynamic the Text property for the TextBlock in the WPF application in the runtime.
Here is the code:
In xaml file
<DataTemplate x:Key="Double_View_Template">
<TextBlock
x:Name="txtDoubleViewTemplate"
HorizontalAlignment="Left"
VerticalAlignment="Center"
/>
</DataTemplate>
In C#
DataTemplate data = FindResource("Double_View_Template") as DataTemplate;
TextBlock ui = data.LoadContent() as TextBlock;
Binding binding = new Binding();
binding.Path = new PropertyPath("Mass");
BindingOperations.SetBinding(ui, TextBlock.TextProperty, binding);
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.CellTemplate = data;
instrumentDataGrid.Columns.Add(column);
When run the application I see only blank lines, and the values are not shown in the Datagrid. The ItemsSource and the DataContext is correctly set.
If I set
Text="{Binding Path=Mass}"
in the xaml the data is displayed.
Any idea why in the runtime the binding is not set?
I am having one problem related to ComboBox of DataGrid. Data is binding but it is not showing in the ComboBox after binding. My code is like below:
<my:DataGridTemplateColumn Header="UsgSrc">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbUsgSrc"
ItemsSource="{Binding Source={StaticResource UsgSrcUOMS}}"
SelectedValue="{Binding Path=UsgSrc}"
SelectedValuePath="UtType"
DisplayMemberPath="UtType">
</ComboBox>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
Code for static resource:
UsgSrcUOMS.ObjectDataProvider UsageSrcUOMS = null;
UsageSrcUOMS = (ObjectDataProvider)FindResource("UsgSrcUOMS");
UsageSrcUOMS.ObjectInstance = objUtView;
Microsoft.Windows.Controls.DataGridCell cell = obj.GetCell(dgMtrHdr, J, 11);
if (cell != null)
{
ContentPresenter panel = cell.Content as ContentPresenter;
if (panel != null)
{
ComboBox cmbUsUtilit = obj.GetVisualChild<ComboBox>(panel);
cmbUsUtilit.IsEnabled = true;
if(objUtView!=null)
cmbUsUtilit.ItemsSource = objUtView;cmbUsUtilit.SelectedIndex=2;
}
}
What is the reason for this. Please help me to solve my problem.
Have you tried to change the Binding to the StaticResource, something like that
<ComboBox Name="cbUsgSrc"
ItemsSource="{StaticResource UsgSrcUOMS}"
SelectedValue="{Binding Path=UsgSrc}"
SelectedValuePath="UtType"
DisplayMemberPath="UtType">
</ComboBox>
I am trying to Bind the TextBlock inside ComboBox through Code. I am able to bind the textblock sucessfully but For some reasons TextBlock doesnt display Text Values.
I have mechanism which checks for the selected values and there I am getting the selected values without any problem.
So to conclude, My binding is working fine but I am missing out something hence textblock is not displaying text that is bound with it.
This is the code I am using for Binding:
where "lObjTextBlock" is TextBlock inside of ComboBox.
TextBlock lObjTextBlock = (TextBlock)ComboBox.ItemTemplate.LoadContent();
Binding lObjBinding = new Binding();
lObjBinding.Path = new PropertyPath("[" + lObjMap.PropertyName + "]");
lObjTextBlock.SetBinding(TextBlock.TextProperty, lObjBinding);
This is the XAML for the TextBlock:
<my:HComboBox Name="cmbRefDoctor">
<my:HComboBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="txtRefDoctorName" />
</DataTemplate>
</my:HComboBox.ItemTemplate>
</my:HComboBox>
Once again : My problem is that TextBlock is not displaying any Text althought values are being set.
Would love to get all possible suggestions. Thanks in advance.
it's one of the way to bind controls which inside datatemplate
this.DataContext = Person;
Binding binding = new Binding();
binding.Source = ob;
DataTemplate dtemp = (DataTemplate)Resources["PointTemp"];
Border bdr = dtemp.LoadContent() as Border;
TextBlock tblk = bdr.Child as TextBlock;
tblk.SetBinding(TextBlock.TextProperty, binding);
Here I used ob as double collection assign to textproperty by binding source
<UserControl.Resources>
<DataTemplate x:Key="PointTemp">
<Border Margin="0,23,0,0" Background="Transparent">
<TextBlock Text="{Binding}" Foreground="White" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center"/>
</Border>
</DataTemplate>
</UserControl.Resources>
And you can assign,
if it's combobox or listbox
Here Person is a class name, or set the class name in combobox itemsource