MahApps adding controlzex:ToolTipAssist.AutoMove programatically - c#

I'm adding buttons to a Grid programatically like the code below in a MahApps Metro program. This works fine and the buttons are visible and clickable.
var tooltip = new ToolTip()
{
Content = "ToolTip Text"
};
var button = new Button()
{
Name = "Button1",
Focusable = false,
ToolTip = tooltip,
Content = "ClickMe"
};
button.Click += Button1_Click;
Grid.SetRow(button, 2);
Grid.SetColumn(button, 5);
MainGrid.Children.Add(button);
But I want to use the ToolTipAssist.AutoMove. In the designer you add it like this
<Button Name="Button1" Content="ClickMe">
<Button.ToolTip>
<ToolTip controlzex:ToolTipAssist.AutoMove="True" Content="ToolTip Text" />
</Button.ToolTip>
</Button>
But I haven't been able to add it in code. using ControlzEx; is present in the code. I've tried:
tooltip.controlzex //controlzex does not exist
tooltip.ToolTipAssist //ToolTipAssist does not exist
tooltip.AutoMove //AutoMove does not exist
So I'm thinking it has to be an event that has to be attached somehow, but which one?

The AutoMove property is an attached property, that exposes these methods:
public static bool GetAutoMove(ToolTip element) { //... }
public static void SetAutoMove(ToolTip element, bool value) { //... }
You set AutoMove like this to the tooltip in your code:
ToolTipAssist.SetAutoMove(tooltip, true);

Related

How to change Fontawesome.wpf Icon in c# code

I'm fairly new to programming in wpf, so this might be pretty basic, but I have no Idea how to change a FontAwesome Icon of a button dynamically (in c# code). I use the nuget package as described in this post here. However the last part:
And finally in your C# code behind:
using FontAwesome.WPF; // on the top of the code
btnButton.Content = FontAwesomeIcon.LongArrowRight;
is not working for me, as it only shows the text "LongArrowRight" after clicking the button.
This is my code:
<Window
...
xmlns:fa="http://schemas.fontawesome.io/icons/">
<Grid>
<Button x:Name="btnPlay" Click="btnPlay_Click">
<Button.Content>
<fa:ImageAwesome Icon="Play"/>
</Button.Content>
</Button>
</Grid>
</Window>
using FontAwesome.WPF; // at the top
private bool running = false;
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
if (running)
{
running = false;
btnPlay.Content = FontAwesomeIcon.Play;
}
else
{
running = true;
btnPlay.Content = FontAwesomeIcon.Stop;
}
}
As already stated when the button is clicked it does not show the Icon but only the text "Stop" and when pressed again "Play".
FontAwesomeIcon is enum. When you assign enum value to Button.Content it will be displayed as text.
You need to assign ImageAwesome element to Content:
btnPlay.Content = new ImageAwesome { Icon = FontAwesomeIcon.LongArrowRight };
btnPlay.Content = new ImageAwesome { Icon = FontAwesomeIcon.Play };
btnPlay.Content = new ImageAwesome { Icon = FontAwesomeIcon.Stop };

Binding Label's visible property in a list with Toggle switch

I have a toggle button and list which contains Label in it.
Toggle(Switch) and List View are declared in Xaml file where list's Data-cell is generated programatically in cs file.
I need to hide/show this label in the list based on the toggle switch
Xaml code:
<Switch IsToggled="{Binding IsToggled, Mode=TwoWay}" Grid.Row = "0" Grid.Column = "1" HorizontalOptions = "Start" Margin = "10,8,8,0"></Switch>
<ListView x:Name="lvItemSigns" HasUnevenRows="True" SeparatorVisibility="Default" SeparatorColor="Gray">
cs file code:
lvItemSigns.ItemTemplate = new DataTemplate(typeof(DataCell));
lvItemSigns.ItemsSource = VM.ItemSignsList;
class DataCell : ViewCell
{
Label label;
public DataCell()
{
// has grid
var label = new Label();
label.TextColor = Color.Black;
label.Margin = 4;
label.Text = "test";
grid.Children.Add(label, 2, 1);
label.SetBinding(Label.IsVisibleProperty, new Binding("BindingContext.IsToggled", BindingMode.TwoWay, new BooleanConverter(), null, null, "cs-file_name"));
grid.Children.Add(stackLayout, 0, 3);
grid.Margin = new Thickness(8,0,0,0);
View = grid;
}
}
In ViewModel:
public bool _IsToggled;
public bool IsToggled
{
get
{
return _IsToggled;
}
set
{
_IsToggled= value;
OnPropertyChanged("_IsToggled");
}
}
public ItemSignsTabViewModel()
{
ItemSignsList = new ObservableCollection<TicketItem>(daItemSign.GetItemSigns(Ticket.MobileID));
}
I'm binding the visible property to Label but still I can see the label all the time (when toggle switch is on or off).
I know I'm doing something wrong. Any help?
Your DataContext for the Switch's binding is different from you DataCell's DataContext.
Both views are not targeting the same objects.
You need to post the code of your viewmodels for both the page, and the DataCell in order to get help.

WPF - get all children from code

Here is my problem : I created a programm with Fluent ribbon, and when I want to disable a ribbon, I need to use the following code :
Code WPF :
<Fluent:RibbonGroupBox x:Name="GpRibbonFormats" ...>
<Fluent:Button x:Name="AjoutTole" Header="{x:Static p:Resources.Ajouter}">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipAjoutTole"...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
<Fluent:Button x:Name="EditQtyFormat" ...>
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipEditQtyFormat"...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
<Fluent:Button x:Name="DeleteFormat" SizeDefinition="Large">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipDeleteFormat" ...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
</Fluent:RibbonGroupBox>
Code Behind :
AjoutTole.IsEnabled = false;
ScreenTipAjoutTole.DisableReason = isBlocked;
EditQtyFormat.IsEnabled = false;
ScreenTipEditQtyFormat.DisableReason = isBlocked;
DeleteFormat.IsEnabled = false;
ScreenTipDeleteFormat.DisableReason = isBlocked;
It works fine but I would like to make a function like that, so I am sure I always send correct information in DisableReason :
DisableButton(Fluent:Button NameOfButton,string ReasonOfDisable)
{
NameOfButton.IsEnabled = false;
NameOfButton.AllScreenTipChild.DisableReason=ReasonOfDisable
}
The same way I would like to disable all a group of buttons :
DisableGroup(Fluent:RibbonGroupBox myGroup,string ReasonOfDisable)
{
foreach(Fluent:Button button in myGroup)
{
button.isEnable=false;
button.AllScreenTipChild.DisableReason=ReasonOfDisable;
}
}
How such a thing is it possible?I want to be able to do it from codebehind.
Edit :
When trying to get the children of my button, I return one element of type System.Windows.Controls.Border, which name is "border", but I don't have such element in my XAML file.
I also tried to get children of my RibbonGroupBox, but in that case I return one grid (grid2), and that grid is not even in the Ribbon...
Code used :
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(DeleteOL); i++)
{
var child = VisualTreeHelper.GetChild(DeleteOL, i);
string monType = child.GetType().ToString();
if(monType== "System.Windows.Controls.Border")
{
System.Windows.Controls.Border bb = (System.Windows.Controls.Border)child;
string name = bb.Name;
}
}
Edit 2 :
I confirm that getChild doesn't work on ribbon(why?), but I could find how to get list of buttons in a group :
foreach(var item in GpRibbonFormats.Items)
{
if(item.GetType().ToString()=="Fluent.Button")
{
Fluent.Button button = (Fluent.Button)item;
button.IsEnabled = false;
}
}
Now I am still looking on how to find a button's ScreenTip
You seem to mix namespace convention from XAML and C#, in C# you don't use : to reference a namespace, you use . separator instead. For example, StackPanel is inside System.Windows.Controls namespace, so you refer to it like this in C# :
System.Windows.Controls.StackPanel stackPanel = new System.Windows.Controls.StackPanel();
I never tried Fluent, but this code should work.
public void DisableGroup(Fluent.RibbonGroupBox ribbonGroup, string reasonOfDisable)
{
foreach (var item in ribbonGroup.Items)
{
if (item is Fluent.Button)
{
DisableButton((Fluent.Button)item, reasonOfDisable);
}
}
}
public void DisableButton(Fluent.Button button, string reasonOfDisable)
{
button.IsEnabled = false;
if (button.ToolTip is Fluent.ScreenTip)
{
Fluent.ScreenTip screenTip = (Fluent.ScreenTip)button.ToolTip;
screenTip.DisableReason = reasonOfDisable;
}
}
To disable an entire group, you call it like this
DisableGroup(GpRibbonFormats, "Ce groupe n'est pas disponible");
To disable only one button, you call it like this
DisableButton(AjoutTole, "Ajouter est désactivé pour le moment");
By the way, Fluent.RibbonGroupBox inherits from ItemsControl, this control has its own IsEnabled property, you can probably disable an entire group by just setting the property to false (I've not tested it though), but you'll have to go through each button to set their screentip anyway.
GpRibbonFormats.IsEnabled = false;
For this kind of thing, Binding are very powerful in WPF, you might want to read a bit on MVVM. It's not easy to implement at first, but once you get the hang of it, it's a game changer and really simplifies your code and logic.
It took time to me, but I finally understood what users were trying to explain to me (it is not obvious for somebody starting with MVVM, that's why I write it here).
I believed I could easily set my properties IsEnabled to true or false in the code(As in Roger Leblanc answer), then continue binding my ViewModel.
It is not so, as when I set my IsEnable (to true) Property, it replaces IsEnabled="{Binding EnableEditNesting}" by IsEnabled=true, so after that no more binding is done(tell me if I am wrong).
On the end I did the following :
For the GroupBox that don't need different behaviour for each button, I just put a binding on its IsEnable parameter.
<Fluent:RibbonGroupBox x:Name="GpRibbonFormats" IsEnabled="{Binding EnableGpRibbonFormats}" Header="{x:Static p:Resources.Stock}">
<Fluent:RibbonGroupBox.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipGpRibbonFormats" Image="img\image_engrenage.png" Width="250" Text="{x:Static p:Resources.NestingSendToProduction}" DisableReason="{Binding EnableGpRibbonFormatsReason}">
</Fluent:ScreenTip>
</Fluent:RibbonGroupBox.ToolTip>
<Fluent:Button x:Name="AjoutTole" SizeDefinition="Large" LargeIcon="img\image_add.png" Header="{x:Static p:Resources.Ajouter}" Click="Add_ToleOL_Click">
</Fluent:Button>
...
</Fluent:RibbonGroupBox>
For the GrouBox where I need specific behaviour on each button, I put a Binding for each of the buttons(nothing on the group), and when I need to disable all the group, I then disable buttons one by one.
<Fluent:RibbonGroupBox x:Name="GpRibbonOL" Header="{x:Static p:Resources.NestingLaunchingOrder}">
<Fluent:Button x:Name="DeleteOL" IsEnabled="{Binding EnableDeleteOL}" SizeDefinition="Large" LargeIcon="img\image_delete.png" Header="{x:Static p:Resources.Supprimer}" Click="Supprimer_OF">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipDeleteOL" Image="img\image_delete.png" Title="Delete OL" Width="250" Text="Delete element" DisableReason="{Binding EnableEditNestingReason}">
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
...
</Fluent:RibbonGroupBox>
ViewModel looks like that, so when I want to Enable/Disable, I just change the tooltip :
private bool enableGpRibbonNesting;
public bool EnableGpRibbonNesting
{
get { return enableGpRibbonNesting; }
set
{
enableGpRibbonNesting = value;
this.NotifyPropertyChanged("EnableGpRibbonNesting");
}
}
private string enableGpRibbonNestingReason;
public string EnableGpRibbonNestingReason
{
get { return enableGpRibbonNestingReason; }
set
{
enableGpRibbonNestingReason = value;
if (value == "")
{
EnableGpRibbonNesting = true;
}
else
{
EnableGpRibbonNesting = false;
}
this.NotifyPropertyChanged("EnableGpRibbonNestingReason");
}
}

XAMLstackpanel creation in c# DragOver Drop

Im working on creating StackPanels in C#.
The xaml Im trying to replicate in C# is
<StackPanel Grid.Column="0" Background="BlanchedAlmond" DragOver="panel_DragOver" Drop="panel_Drop" AllowDrop="True" MinWidth="150">
Currently what I have is:
StackPanel myPanel = new StackPanel
{
MinWidth = 150,
MinHeight = 150,
AllowDrop = true
};
MainStack.Children.Add(myPanel);
Which currently works the only issue is that the StackPanel does not have the properties for DragOver and Drop, how can I add this to the C# code?
These are not properties but events that you can hook up handlers to using the += syntax:
StackPanel myPanel = new StackPanel
{
MinWidth = 150,
MinHeight = 150,
AllowDrop = true
};
myPanel.DragOver += panel_DragOver;
myPanel.Drop += panel_Drop;
MainStack.Children.Add(myPanel);
Of course the handlers, panel_DragOver and panel_Drop, must still be defined just like before.
Yes, it does have it.
var sp = new StackPanel();
sp.Drop += (o, arg) => { };
You just cannot assign an event within the body of object creation.

How can I add a hint or tooltip to a label in C# Winforms?

It seems that the Label has no Hint or ToolTip or Hovertext property. So what is the preferred method to show a hint, tooltip, or hover text when the Label is approached by the mouse?
You have to add a ToolTip control to your form first. Then you can set the text it should display for other controls.
Here's a screenshot showing the designer after adding a ToolTip control which is named toolTip1:
yourToolTip = new ToolTip();
//The below are optional, of course,
yourToolTip.ToolTipIcon = ToolTipIcon.Info;
yourToolTip.IsBalloon = true;
yourToolTip.ShowAlways = true;
yourToolTip.SetToolTip(lblYourLabel,"Oooh, you put your mouse over me.");
System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();
ToolTip1.SetToolTip( Label1, "Label for Label1");
just another way to do it.
Label lbl = new Label();
new ToolTip().SetToolTip(lbl, "tooltip text here");
Just to share my idea...
I created a custom class to inherit the Label class. I added a private variable assigned as a Tooltip class and a public property, TooltipText. Then, gave it a MouseEnter delegate method. This is an easy way to work with multiple Label controls and not have to worry about assigning your Tooltip control for each Label control.
public partial class ucLabel : Label
{
private ToolTip _tt = new ToolTip();
public string TooltipText { get; set; }
public ucLabel() : base() {
_tt.AutoPopDelay = 1500;
_tt.InitialDelay = 400;
// _tt.IsBalloon = true;
_tt.UseAnimation = true;
_tt.UseFading = true;
_tt.Active = true;
this.MouseEnter += new EventHandler(this.ucLabel_MouseEnter);
}
private void ucLabel_MouseEnter(object sender, EventArgs ea)
{
if (!string.IsNullOrEmpty(this.TooltipText))
{
_tt.SetToolTip(this, this.TooltipText);
_tt.Show(this.TooltipText, this.Parent);
}
}
}
In the form or user control's InitializeComponent method (the Designer code), reassign your Label control to the custom class:
this.lblMyLabel = new ucLabel();
Also, change the private variable reference in the Designer code:
private ucLabel lblMyLabel;
I made a helper to make life easier.
public static class ControlUtilities1
{
public static Control AddToolTip(this Control control, string title, string text)
{
var toolTip = new ToolTip
{
ToolTipIcon = ToolTipIcon.None,
IsBalloon = true,
ShowAlways = true,
ToolTipTitle = title,
};
toolTip.SetToolTip(control, text);
return control;
}
}
Call it after controls are ready:
InitializeComponent();
...
linkLabelChiValues.AddToolTip(title, text);
It's an way to keep consistent tool tip styles.

Categories

Resources