How to show tooltip for IntegerUpdown control? - c#

I try to make tooltip on DevExpress IntegerUpDown (DoubleUpDown and so on) control:
<xcd:DoubleUpDown
HorizontalAlignment="Stretch"
Margin="5,2"
Grid.Column="0"
Minimum="0"
Value="{Binding SomeValue,Mode=TwoWay,UpdateSourceTrigger=LostFocus}"
Text="{Binding SomeValue,Mode=TwoWay,UpdateSourceTrigger=LostFocus}"
ToolTip="{Binding SomeValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
>
</xcd:DoubleUpDown>
But, it do not work for me - only empty tooltip shows.
How to make tooltip?

If you see an empty ToolTip at runtime, it is your binding that fails.
Try to set the ToolTip property to a hard-coded value and you should see that it works:
ToolTip="Test"
You then know that there is something wrong with your binding. Make sure that the DoubleUpDown control has a DataContext that has a public SomeValue property that returns the value you are expecting to show up in the tooltip.
Also note that it makes no sense to set the Mode property to TwoWay and the UpdateSourceTrigger property to PropertyChanged on a ToolTip binding.

Related

WPF nested property binding not working if parent property is null

I have the following situtation:
<DatePicker IsEnabled="{Binding ParentObject.EditAvailable}"
Now if I set ParentObjectto nullin my ViewModel which is also the DataContext the IsEnabled Property on the DatePicker will be set to true
The binding is working completely correct for all instances if the ParentObject is properly set.
But I don't really get that behavior in WPF.
A workaround would be using:
<DatePicker IsEnabled="{Binding ParentObject.EditAvailable, FallbackValue=False}"
So now if the ParentObject is set to null via my ViewModel, the IsEnabled property on the DatePicker returns false.
Is there anything I can do without setting the FallbackValue on each of my controls in my project?
It's already huge and I need to find a solution to have it somehow as default behavior that if the ParentObject is null, that there is a default value set default(bool), default(string) etc etc.
Any help is much appreciated.
You can set IsEnabled on the panel or grid that contains the controls, and it will affect all controls it contains.
<StackPanel IsEnabled="{Binding ParentObject.EditAvailable, FallbackValue=False}">
<DatePicker />
<DatePicker />
<DatePicker />
</StackPanel>
Is there anything I can do without setting the FallbackValue on each of my controls in my project?
No, not apart from replacing each binding with a custom one that sets the FallbackValue by default. See this answer for an example.
You will still have to replace {Binding with {local:YourBinding everywhere.
If binding Path is always the same, then you can use default style for DatePicker:
<Style TargetType="DatePicker">
<Setter Property="IsEnabled" Value="{Binding ParentObject.EditAvailable, FallbackValue=False}"/>
</Style>

Binding a TextBlock 's Text property to current existing DataContext

For a TextBlock control, I want the Text property to be depending on the current DataContext, and I will display some very nice formatted string-- depending on the type of the DataContext-- with an IValueConverter to properly convert the Text property.
How to do this?
A Binding without a Path (or with Path=.) binds directly to the object in the DataContext of the the TextBlock:
<TextBlock Text="{Binding Converter={StaticResource ...}}" />

Dependency Property Datacontext

I have a usercontrol, and there is a Datacontext set for it. This usercontrol contains also a Dependency-Property. Now, i want simply bind to this property.
I think the problem has something to do with the wrong datacontext.
The dependency-Property in my usercontrol (called TimePicker) looks like this:
public TimeSpan Time
{
get { return (TimeSpan)GetValue(TimeProperty); }
set
{
SetValue(TimeProperty, value);
OnPropertyChanged();
}
}
public static readonly DependencyProperty TimeProperty = DependencyProperty.Register("Time", typeof (TimeSpan), typeof (TimePicker));
I try to use it like this:
<upDownControlDevelopement:TimePicker Grid.Row="1" Time="{Binding Path=TimeValue}" />
When i do this i get the following binding error:
System.Windows.Data Error: 40 : BindingExpression path error: 'TimeValue' property not found on 'object' ''TimePicker' (Name='TimePickerControl')'. BindingExpression:Path=TimeValue; DataItem='TimePicker' (Name='TimePickerControl'); target element is 'TimePicker' (Name='TimePickerControl'); target property is 'Time' (type 'TimeSpan')
Any help would be highly appreciated
Greetings Michael
PS: you can download the code at here
Although this has now been solved there seems to be some, in my opinion, inappropriate use of the DataContext.
When developing a custom reusable control, you should not set DataContext at all. What the DataContext will be, that is for the user of the control to decide, not for the developer. Consider the following common pattern of code:
<Grid DataContext="{Binding Data}">
<TextBox Text="{Binding TextValue1}" />
<!-- Some more controls -->
</Grid>
Notice that here, you are using the Grid control. The developer of the control (in this case, the WPF team), didn't touch the DataContext at all - that is up to you. What does it mean for you as a control developer? Your DependencyProperty definition is fine, but you shouldn't touch the DataContext. How will you then bind something inside your control to the DependencyProperty value? A good way is using a template (namespaces omitted):
<MyTimePicker>
<MyTimePicker.Template>
<ControlTemplate TargetType="MyTimePicker">
<!-- Stuff in your control -->
<TextBlock Text="{TemplateBinding Time}" />
<TextBox Text="{Binding Time, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
<MyTimePicker.Template>
</MyTimePicker>
Note that TemplateBinding is always one-way only, so if you need any editing at all, you need to use normal binding (as you can see on the TextBox in the example).
This only means that the TextBlock/Box inside your control will get its Time value from your custom control itself, ignoring any DataContext you might have set.
Then, when you use the control, you do it like this (added to my first example):
<Grid DataContext="{Binding Data}">
<TextBox Text="{Binding TextValue1}" />
<!-- Some more controls -->
<MyTimePicker Time="{Binding TimeValue}" />
</Grid>
What just happened here is that the MyTimePicker does not have DataContext set anywhere at all - it gets it from the parent control (the Grid). So the value goes like this: Data-->(binding)-->MyTimePicker.Time-->(template binding)-->TextBlock.Text.
And above all, avoid doing this in the constructor of your custom control:
public MyTimePicker()
{
InitializeComponent();
DataContext = this;
}
This will override any DataContext set in XAML, which will make binding a huge pain (because you'll have to always set Source manually). The previous example would not work, and this wouldn't work either:
<MyTimePicker DataContext="{Binding Data}" Time="{Binding TimeValue}" />
You would think this is OK, but the DataContext will be resolved in the InitializeComponent() call, so the value will be immediately overwritten. So the binding to TimeValue will look for it in the control instead (which will, of course, fail).
Just don't touch the DataContext when developing a control and you'll be fine.
You don't need to override the data context of user control. You can use RelativeSource to point your binding source property i.e. TimeValue to any other source you like. E.g. If you have the source property in your window's class. You could simply point your binding target to the source in window's data context as follows:
{Binding Path=DataContext.TimeValue, RelativeSource={ RelativeSource AncestorType={x:Type Window}}}
Your error states that 'TimeValue' property not found on 'object' 'TimePicker', which means that the WPF Framework is looking at the 'TimePicker' object to resolve the 'TimeValue' property value. You must have somehow set the DataContext of the Window or UserControl that contains the 'TimePicker' object to an instance of the 'TimePicker' object.
Instead, it should be set to an instance of the class that declares the 'TimeValue' property. If you're using a view model, then you should set it to an instance of that:
DataContext = new YourViewModel();
If the 'TimeValue' property is declared in the Window or UserControl then you can set the DataContext to itself (although generally not recommended):
DataContext = this;
Please note that when data binding to the 'Time' property from inside your TimePicker control, you should use a RelativeSource Binding:
<TextBlock Text="{Binding Time, RelativeSource={RelativeSource
AncestorType={x:Type YourLocalPrefix:TimePicker}}}" ... />
Normally we are not setting datacontext directly.If u want to set datacontext create an instance of your usercontrol and set datacontext individually to each one.

WPF binding view data doesn't update correctly

I have this code part:
<TextBlock
Margin="5,3,5,1" Foreground="White"
FontWeight="Bold" FontStyle="Italic" TextAlignment="Center"
Text="{Binding AntennaName}"/>
and in my viewmodel:
private string antennaName;
public string AntennaName
{
get { return antennaName; }
set { antennaName = value; OnPropertyChanged("AntennaName"); }
}
I checked and I can confirm that in my actual code the AntennaName property does change but the textblock does not.
Can anyone please explain why is this happening? I'm pretty new to the mvvm scene.
Try this -
<TextBlock Text="{Binding DataContext.AntennaName,
RelativeSource={RelativeSource FindAncestor,
AncestorType=UserControl}}"/>
The problem somewhere lies in the way you are setting the DataContext for your UserControl. Somehow, textBlock is not inheriting the DataContext from its parent(UserControl). So, explicitly asking for it might work.
Explanation
UI elements by default search for the Binding in its DataContext unless explicitly specified to look into some other place.
Also, in case you haven't set the DataContext for the control, it will inherit DataContext from its parent Control and look for the Binding property in it. In case the binding property is not found on the parent DataContext either, binding fails silently and all you will see is empty string.
You can always look for Binding failures in the output window. If you look in the output window, you will see your property AntennaName over there.
Refer - Data Binding Overview

In WPF how to get binding of a specific item from the code?

The example of this would be:
A textBox is bound to some data. There is a second text box which is not bind to anything. So I want to bind text box 2 to the same data 1st textBox is bound.
In other words I wan't to know if the DependencyObject stores some reference to it's data-bindings? If not, what is the way to find out all data-bindings of a specific object?
Try this
Xaml
<TextBox Name="textBox1" Text="{Binding Text1}"/>
<TextBox Name="textBox2" Text="No Binding"/>
Then we can set the binding of the TextProperty for textBox2 to the same as textBox1 with this code behind
BindingExpression bindingExpression = textBox1.GetBindingExpression(TextBox.TextProperty);
Binding parentBinding = bindingExpression.ParentBinding;
textBox2.SetBinding(TextBox.TextProperty, parentBinding);
You can get the binding of any dependency object using
System.Windows.Data.BindingOperations.GetBinding(DependencyObject target,DependencyProperty dp)
then set the binding with
System.Windows.FrameworkElement.SetBinding(DependencyProperty dp, string path)
For example:
var binding = BindingOperations.GetBinding(textBox1,TextBox.TextProperty);
textBox2.SetBinding(TextBox.TextProperty, binding);
I know there's already an accepted answer, but is there some reason you're just not doing this?
<TextBox Name="textBox1" Text="{Binding Text1}"/>
<TextBox Name="textBox2" Text="{Binding Text, ElementName=textBox1}"/>
Now whatever textBox1 is bound to, even if that binding changes, textBox2 is as well, no code-behind needed.
Granted I'm basing this on the XAML as presented, and you very well may need the binding itself from code for something else, but if not, the above works just fine.
You can do this in code by calling the SetBinding method.

Categories