In my custom control I want to programmaticaly enable or disable tooltip depending on options. Here is how my icon defined in template:
<Image x:Name="PART_IconImage" Stretch="None" VerticalAlignment="Top" HorizontalAlignment="Center" Source="{TemplateBinding Icon}"
ToolTipService.ToolTip="{TemplateBinding Caption}" />
I'm using this code to access ToolTip and to enable/disable it:
// Enable tooltip when caption not shown
if (this.IconImage != null)
{
var toolTip = ToolTipService.GetToolTip(this.IconImage) as ToolTip;
if (toolTip != null)
toolTip.IsEnabled = this.CaptionVisibility.HasValue
? (this.CaptionVisibility.Value == Visibility.Collapsed)
: (this.ParentToolbar.CaptionsVisibility == Visibility.Collapsed);
}
GetToolTip returns null. Any idea why?
P.S. I was following this advice here: How to programmatically access ToolTipService of a Silverlight FrameworkElement?
But it doesn't work for me.
Are you sure that ToolTipService.GetToolTip is returning null, as opposed to returning something other than a ToolTip?
I did a quick experiment with code similar to yours and found that ToolTipService.GetToolTip returned a string. I was of course binding ToolTipService.ToolTip to a string dependency property. I suspect you're also getting a string back from GetToolTip, but the as ToolTip you have added after the call to this method nulls out this string.
One way to programmatically disable the tooltip is to bind it to a property on the view-model which contains the tooltip text if the tooltip should be shown or null if the tooltip should not be shown.
Alternatively, you can use a ToolTip, instead of a string, as the tooltip for your control. That way you should be able to access the ToolTip object and enable/disable it in your code above:
<Image x:Name="PART_IconImage" Stretch="None" VerticalAlignment="Top" HorizontalAlignment="Center" Source="{TemplateBinding Icon}">
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock Text="{TemplateBinding Caption}" />
</ToolTip>
</ToolTipService.ToolTip>
</Image>
Why don't you simply bind property below with a bool property?
ToolTipService.IsEnabled
Then whenever you want to disable/enable simply change the binded property
< Image ToolTipService.IsEnabled="{Binding Path=SomeProperty}">
Also take a look at How do you disable tooltips in code at runtime
Related
I have custom control like below. When press tab key focus will move in the order elements arrangement.
Query:
When stackpanel receive tab focus I need to change default tab order toggle button present in stackpanel
Default Tab Order:
DockPanel--Border---StackPanel-->Button1-->button2-->button3
Expected Order
DockPanel--Border---StackPanel-->Button3-->button2-->button1
I need update TabOrder based on its parent. Please suggestion solution modify the tab order based on parent
Note: I need UI as like below arrangements, only i need to modify the tab order for buttons
<DockPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="MainBorder">
<StackPanel>
<ToggleButton>Button 1</ToggleButton>
<ToggleButton>Button 3</ToggleButton>
<ToggleButton>Button 3</ToggleButton>
</StackPanel>
</Border>
</DockPanel>
As mentioned in comments do set the TabIndex property. To step within control do use KeyboardNavigation.TabNavigation attached property.
<DockPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="MainBorder">
<StackPanel KeyboardNavigation.TabNavigation="Local">
<ToggleButton KeyboardNavigation.TabIndex="3">Button 1</ToggleButton>
<ToggleButton KeyboardNavigation.TabIndex="2">Button 2</ToggleButton>
<ToggleButton KeyboardNavigation.TabIndex="1">Button 3</ToggleButton>
</StackPanel>
</Border>
</DockPanel>
If you want to modify the tab order at run time I would advice you to create a behavior for it. See Use of Behavior in WPF MVVM? To access attached property from code see Get and set WPF custom attached property from code behind
I have a very simple XAML
Visibility="Collapsed" X1="1" Margin="-35 0 0 0" Y1="0.4">
<Label.Content>
<Slider Grid.Column="0"
Width="20"
Height="65"
IsDirectionReversed="True"
Maximum="0.1"
Minimum="-4"
Orientation="Vertical"
x:Name="Slider1"
Value="{Binding Source={x:Reference scaleFactorModifier},
Path=ZoomScaleFactor, Mode=TwoWay}" />
</Label.Content>
</Label>
</SciChart:CustomAnnotation.Content>
</SciChart:CustomAnnotation>
Now for some reason I need to set the CustomControl.Content property from code behind. Is there any possibility I move all the label control to some style and template and set the CustomControl content property at runtime with that particular style or template.
Update
Reason for using Code behind
Actually I have Annotations property in my control which could have any control in it as we required. Previously I had used hard coded annotations in my control and placed the controls manually. Now I want to bind the Annotations property. I could create a property of this type and add CustomAnnotation objects in it. But customAnnotation objects need to have labels and other controls in them, how could I do that?
If I have understood your problem correctly, I believe that you can do what you want by using a DataTemplate and a ContentControl. First, define a DataTemplate with your Label in:
<DataTemplate DataType="{x:Type YourPrefix:YourDataType}">
<!-- define your Label here -->
</DataTemplate>
Then you can set the Content property of your CustomControl to a ContentControl that has its own Content property set to an instance of an object of type YourDataType:
<ContentControl Content="{Binding InstanceOfYourDataType}" />
I'm aware that you want to do this programmatically, but that's easy enough to work out:
ContentControl contentControl = new ContentControl();
contentControl.Content = instanceOfYourDataType;
yourCustomControl.Content = contentControl;
I'm wondering if you even really need to use your CustomControl at all, but I'll leave that up to you.
I create a user control from that xaml and then set the CustomControl.Content as new instance of user control. This might not be the best solution, but this is all that I have for now.
I have the following AppBar.
<Page.BottomAppBar>
<AppBar x:Name="bottomAppBar" Padding="10,0,10,0">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="switchMeasurementMode" AutomationProperties.Name = "Breath rate" Style="{StaticResource AppBarButtonStyle}" Click="switchMeasurementMode_Click" />
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
It looks like this
I tend to change its text during run-time with the following C# code
private void switchMeasurementMode_Click(object sender, RoutedEventArgs e)
{
this.switchMeasurementMode.Name = "111";
}
But the button text is not changed. Is there anything I had missed out?
If you use the default styles for AppBar in Windows 8 C# projects, then you have to change the attached property AutomationProperties.Name either in XAML using:
AutomationProperties.Name = "new name"
or in code using:
Button.SetValue(AutomationProperties.NameProperty, "new value");
or
AutomationProperties.SetName(Button, "new value");
The button is a content control. You set the Content property to change the content.
this.switchMeasurementMode.Content= "111";
The Name property is how you set the programmatic "handle" for the Button. You use the name in the code editor to modify the control. In your case, you are changing the name, which means you loose the ability to say this.switchMeasurementMode...
FYI, content can be more than just text. Most XAML elements can be added as content.
I have a custom component, ExportCommandButton, that has two attached properties. This component is designed to be attached to a button. When clicked, the component would initiate the export method of the grid (Telerik RadGridView). The problem I have is how can I pass the grid to the component via one of the attached properties? I've tried element to element binding, but the GridView set property never fires. How do you bind to a control and not a property of the control?
<Button IsEnabled="{Binding Loaded}"
cmd:ExportCommandButton.GridView="{Binding ElementName=MyGrid}"
cmd:ExportCommandButton.Converter="{StaticResource MyConverter}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="/Assets/xls.png" />
<TextBlock VerticalAlignment="Center" Text="Export" Margin="5,0,0,0" />
</StackPanel>
</Button.Content>
</Button>
Your syntax seems right. The CLR property setter is not called because the binding directly updates the dependency property, without passing by the property which is here for convenience. Use the propertyChangedCallback parameter of your attached property metadata to listen for changes.
I have a WPF textBox that is declared as ReadOnly
<TextBox IsReadOnly="True" IsTabStop="False" Width="200" />
So, User can not write anything into the TextBox or delete the content but it still allows user to drag the text from this textbox and drop it in any other textbox that caused the text removed from the first textbox(the read-only one) and thats unexpected. Is it a bug?
how can I get rid of this?
I tried the following code :
<StackPanel>
<TextBox IsReadOnly="True">Hello</TextBox>
<TextBox></TextBox>
</StackPanel>
When I drag-and-drop the text (after selection) from the first TexbtBox to the second one, the text is copied, but not removed from the first TextBox. I tried it under .NET 3.5 and .NET 4.0 targets.
If you want to get rid of your bug without trying to understand it (since it shouldn't happen), you can just put an empty control (Canvas will be ok) on top of your TextBox, with its Background property set to transparent.
<Grid>
<TextBox IsReadOnly="True" IsTabStop="False" Width="200" />
<Canvas Background="Transparent"/>
</Grid>
But the text won't be selectable anymore...