Adding a ToolTip to a enabled/disabled Picture Control in VB.Net? - wpf

I need to have a tooltip for an image based on if its enabled or not. Right now I can only make it work with a static tooltip for when it's enabled. How can I make it display a different tooltip if it's disabled?
<Button x:Name="Button" Width="21" Height="21" Padding="1,1,2,1" BorderThickness="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" Background="DarkGray">
<Image Source="../../Images/report.png" Stretch="Fill" HorizontalAlignment="Center" Height="20" Width="20" Margin="0,0,0,0" />
</Button>
Public Sub SetButtonEnabled(ByVal arg_blnEnabled As Boolean)
Dim tp As New System.Windows.Forms.ToolTip
If arg_blnEnabled Then
Me.IsEnabled = True
Me.ToolTip = "Reports"
Else
Me.IsEnabled = False
Me.ToolTip = "Please select a Transmittal"
End If
End Sub

Use a Style and do it all in XAML:
<Button x:Name="Button" Width="21" Height="21" Padding="1,1,2,1" BorderThickness="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" Background="DarkGray" ToolTipService.ShowOnDisabled="True">
<Button.Style>
<Style TargetType="Button">
<Setter Property="ToolTip" Value="Reports"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="ToolTip" Value="Please select a Transmittal"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Image Source="../../Images/report.png" Stretch="Fill" HorizontalAlignment="Center" Height="20" Width="20" Margin="0,0,0,0" />
</Button>
Note: you'll have to remove your existing code for setting ToolTip, otherwise it will override this.

Related

How to highlight only one button out of 4 buttons

I have 4 buttons on the screen. When i click one button i am loading Grid data on the same UI.
When I click 2nd button I am just clearing old data and binding new data for the corresponding grid.
I just want to highlight only one Button once i Clicked it.
I am using MVVM pattern so.. need to fix this issue only in XAML.
Example:
I clicked 1st button it will load data on the grid based on selection.
Now button 1 should be highlighted.
When I click on 2nd button. Button 1 should be in normal state and 2nd button should be highlighted.
Only one Button highlight should be in highlighted mode until we are on the view.
You should use WPF triggers. In your case it's IsPressed. Simple example:
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="BorderBrush" Value="1"/>
</Trigger>
Here is a complete example that works for me
<Window.Resources>
<Style x:Key = "TriggerStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property = "IsPressed" Value = "True">
<Setter Property = "Background" Value = "Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="button" Style = "{StaticResource TriggerStyle}" Content="Button" HorizontalAlignment="Left" Margin="103,45,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Style = "{StaticResource TriggerStyle}" Content="Button" HorizontalAlignment="Left" Margin="163,130,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
If it still doesn't work then maybe you should post your xaml.
I think you are looking for RadioButtons.
<Window.Resources>
<ControlTemplate x:Key="RbTemplateKey" TargetType="RadioButton">
<ToggleButton IsChecked="{Binding IsChecked, Mode=TwoWay,RelativeSource={RelativeSource AncestorType=RadioButton, Mode=FindAncestor}}"/>
</ControlTemplate>
</Window.Resources>
<Grid>
<StackPanel Margin="141,148,161,0" Orientation="Horizontal" Background="AliceBlue">
<RadioButton Width="25" Height="25" Margin="10" Template="{StaticResource RbTemplateKey}"/>
<RadioButton Width="25" Height="25" Margin="10" Template="{StaticResource RbTemplateKey}"/>
<RadioButton Width="25" Height="25" Margin="10" Template="{StaticResource RbTemplateKey}"/>
<RadioButton Width="25" Height="25" Margin="10" Template="{StaticResource RbTemplateKey}"/>
</StackPanel>
</Grid>

Change Fill color of Path used as Button Template on MouseOver

I have a button that has it's Template setup to display a Path wrapped in a VisualBrush. The Path has its Fill assigned, but I want to change the Fill color when the button is moused over.
Visual Brush
<VisualBrush x:Key="EditIconBrush" Stretch="Uniform">
<VisualBrush.Visual>
<Canvas Width="24" Height="24">
<Path Fill="White" Data="M20.71,4.04C21.1,3.65 21.1,3 20.71,2.63L18.37,0.29C18,-0.1 17.35,-0.1 16.96,0.29L15,2.25L18.75,6M17.75,7L14,3.25L4,13.25V17H7.75L17.75,7Z" />
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
Button Template
<ControlTemplate x:Key="ButtonIconTemplate"
TargetType="Button">
<Grid>
<Rectangle Fill="Transparent" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Content="{TemplateBinding Content}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</ControlTemplate>
<Button DockPanel.Dock="Right" Margin="0 0 10 0"
Command="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=DataContext.AddFieldCommand}"
Template="{StaticResource ButtonIconTemplate}">
<Rectangle Width="20" Height="20" Fill="{DynamicResource EditIconBrush}" />
</Button>
Do I need to have two different versions of my Path, one in each color? Or can this be achieved in a Style? I'd like to increase the size of the Path when moused over and change its color from grey to white, then decrease the size and change the color from white to grey when the mouse leaves.
I tried to bind the Path's Fill property to the Button's Foreground property, using RelativePath as recommend in another post. I basically wanted to achieve the same concept that the original poster in that thread wanted. The difference being that my Path is in a resource dictionary and not part of my Button itself.
Binding to Foreground attempt
<Button DockPanel.Dock="Right" Margin="0 0 10 0"
Foreground="White"
Command="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=DataContext.AddFieldCommand}"
Template="{DynamicResource ButtonIconTemplate}">
<Rectangle Width="20" Height="20" Fill="{DynamicResource EditIconBrush}" />
</Button>
<VisualBrush x:Key="EditIconBrush" Stretch="Uniform">
<VisualBrush.Visual>
<Canvas Width="24" Height="24">
<Path Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"
Data="M20.71,4.04C21.1,3.65 21.1,3 20.71,2.63L18.37,0.29C18,-0.1 17.35,-0.1 16.96,0.29L15,2.25L18.75,6M17.75,7L14,3.25L4,13.25V17H7.75L17.75,7Z" />
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
I'm not sure how to resolve this issue. Any help would be appreciated.
Use the IsMouseOver trigger:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="NameOfPath" Property="Fill" Value="Colour" />
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="2" ScaleY="2" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
</Trigger>
</ControlTemplate.Triggers>
You'll need to name your paths (e.g. <Path x:Name="NameOfPath" />) and substitute the appropriate colour in plus use an appropriate size for the RenderTransform scale

WPF buttons with both image and text

Here is my control template for the button style.
<StackPanel Orientation="Horizontal">
<Image x:Name="EmailImage" Source="../Images/btn__icon_savedisk.png" Height="17" Width="17" Stretch="None" RenderOptions.BitmapScalingMode="NearestNeighbor" />
<TextBlock x:Name="EmailImageTxt" Margin="20,0,20,0" Foreground="White" Text="{x:Static res:Localize.SAVE}" Background="{x:Null}" />
</StackPanel>
My problem is when I get mouse pointer over the area with the space between image and text button(image and text) is not selecting. I need to have mouse focus on all over the buttons.
Thank you for your help.
Set Background="Transparent" to stackpanel and it works as expected.
An control with no background is usually called as non-hittable in XAML terms. So it is must to set a background to make the object respond to hits.
<Button VerticalAlignment="Center" HorizontalAlignment="Center">
<Button.Template>
<ControlTemplate>
<StackPanel x:Name="stackpanel" Orientation="Horizontal">
<Image x:Name="EmailImage" Source="Black.jpg" Height="17" Width="17" Stretch="None" RenderOptions.BitmapScalingMode="NearestNeighbor" />
<TextBlock x:Name="EmailImageTxt" Margin="20,0,20,0" Foreground="Black" Text="gdfgdg}" Background="{x:Null}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" TargetName="stackpanel"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>

WPF: How to make a Close button on top of a control to show or hide and clickable

I want to show a close button on top of a control only when mouse is over the control, and hide otherwise. Of course, the button should stay when mouse moves from the control to the button. So, I can't simply use IsMouseOver trigger or MouseEnter on the underlining control.
I tried to use a trigger on Grid, but Grid doesn't have IsMouseOver property:
<Grid>
<!-- other controls -->
<Button x:Name="closeButton" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5" Margin="0 -5 -5 0" Padding="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" VerticalAlignment="Top" Background="Transparent" HorizontalAlignment="Right" Command="{Binding HideControlCommand}" ToolTip="Hide">
<Border x:Name="circleBorder" CornerRadius="{Binding ActualHeight, ElementName=circleBorder}" Width="{Binding ActualHeight, ElementName=circleBorder}" BorderBrush="Black" Background="LightGray" Padding="3" BorderThickness="1">
<Grid Name="parent" Width="10" Height="10">
<Line X1="0" Y1="0" X2="{Binding ElementName='parent', Path='ActualWidth'}" Y2="{Binding ElementName='parent', Path='ActualHeight'}" Stroke="Black" StrokeThickness="2" />
<Line X1="0" Y1="{Binding ElementName='parent', Path='ActualHeight'}" X2="{Binding ElementName='parent', Path='ActualWidth'}" Y2="0" Stroke="Black" StrokeThickness="2" />
</Grid>
</Border>
</Button>
<Grid.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Visibility" Value="Visible" TargetName="closeButton"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Visibility" Value="Collapse" TargetName="closeButton"/>
</Trigger>
</Grid.Triggers>
</Grid>
This is very common in web app, but how to do it in wpf?
You can use Datatriggers, i am using this one also for error strip on usercontrol.
Style for stackpanel show hide.
<Style x:Key="PanelStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsException}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding IsException}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
Stackpanel with close button where message(error/warning) will show ..
<StackPanel Margin="10" Style="{StaticResource PanelStyle}">
<StackPanel Orientation="Horizontal">
<StackPanel Margin="10" Background="Red" >
<TextBlock Text="{Binding LstError, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
NotifyOnSourceUpdated=True}" />
</StackPanel>
<Button Width="18" Height="18" Content="X" Command="{Binding CloseStrip}"
HorizontalAlignment="Right" Cursor="Hand" FontSize="12" FontWeight="Bold"
Foreground="#FFEF0909" Padding="0" ToolTip="Close"></Button>
</StackPanel>
</StackPanel>
in viewmodel you have to create a Icomand type property for button.
public DelegateCommand CloseStrip { get; set; }
//this is contructor
public WriteOnStrip()
{
CloseStrip = new DelegateCommand(Close, CanClose);
}
private void Close()
{
LstError = "";
IsException = false;
}
private bool CanClose()
{
return true;
}
I would use css to do this. Just keep the opacity at 0 until you roll over it.
#test {
opacity: 0;
}
#test:hover {
opacity: 1;
}
Check out the js fiddle...
http://jsfiddle.net/qku6a/

Can we have buttons in a validation template, and how can we bind it to the ViewModel method?

Requirement:
Need to display an error message when the user types a forlder name that doesn't exist as shown below:
Problem: I am able to display the UI but not able to call a method in the view model when the user clicks on the button "CreateNew"
View Model Code:
public string this[string columnName]
{
get { return "The entered folder name doesn't exist."; }
}
RelayCommand createNewFolder;
public RelayCommand CreateNewFolder
{
get
{
if (createNewFolder == null)
createNewFolder = new RelayCommand(param => this.OnCreateNewFolder());
return createNewFolder;
}
}
public void OnCreateNewFolder()
{
MessageBox.Show("CreateNewFolder");
}
RelayCommand.cs can be downloaded at: http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=mag200902MVVM&DownloadId=4357
Xaml Code:
<Window.Resources>
<ControlTemplate x:Key="validationTemplate">
<DockPanel LastChildFill="True">
<Border Margin="5,5,0,0" DockPanel.Dock="Bottom" Background="Red">
<StackPanel>
<TextBlock Name="ErrorText" Foreground="White" Background="Red"
FontSize="12" Padding="2" FontFamily="Trebuchet MS"
TextWrapping="Wrap"
Text="{Binding [0].ErrorContent}" ></TextBlock>
<StackPanel Margin="0" Orientation="Horizontal">
<Button Content="Create New" Command="{Binding Path=CreateNewFolder}" Margin="10" Padding="5"></Button>
<Button Content="Cancel" Margin="10" Padding="5" ></Button>
</StackPanel>
</StackPanel>
</Border>
<AdornedElementPlaceholder Name="ErrorTextBox" />
</DockPanel>
</ControlTemplate>
<Style x:Key="ValidationStyle" TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BitmapEffect">
<Setter.Value>
<BitmapEffectGroup>
<OuterGlowBitmapEffect GlowColor="Red" GlowSize="3" Noise="0.6"></OuterGlowBitmapEffect>
</BitmapEffectGroup>
</Setter.Value>
</Setter>
<Setter Property="DataContext"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=DataContext}">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<AdornerDecorator >
<ComboBox IsEditable="True" FontSize="11" Margin="10" Width="250"
VerticalAlignment="Center"
Text="{Binding Path=StrText, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
Style="{StaticResource ValidationStyle}"></ComboBox>
</AdornerDecorator>
</Grid>
Please note that i set the DataContext property in the style:
<Setter Property="DataContext" Value="{Binding RelativeSource={x:Static
RelativeSource.Self},Path=DataContext}">
</Setter>
Please let me know how to bind the method to a button in the validation template.
You could reference the DataContext for the AdornerDecorators Child in the Binding. I think something like this will work
<Button Content="Create New"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type AdornerDecorator}},
Path=Child.DataContext.CreateNewFolder}"
Margin="10" Padding="5"></Button>
This line looks suspicious:
createNewFolder = new RelayCommand(param => this.OnCreateNewFolder());
Maybe you should replace it by:
createNewFolder = new RelayCommand(OnCreateNewFolder);

Resources