Just discovered what is causing a HTML editor to throw the toys out when using a certain letter on a keyboard...
On the same page there are textboxes that contain things like html page name, title, navigate URL, menu text.... If one of the textboxes contains text with an underscore (say 'Test_Page') then the letter 'P' will not function in the HTML editor. I'm guessing (and could be way off base here as I didn't think textbox.txt could do this unlike Label.content) that WPF is taking the text entry and using it as a mnemonic key.. I do know that setting RecognisesAccessKey to false might cure it, but can't find a way to add that property or access ContentPresenter...
This is the class that I use to create the control and ideally would like to set it here
Public Class TBx
Inherits TextBox
Public Shared IsNewRecordProperty As DependencyProperty = DependencyProperty.Register("IsNewRecord", GetType(Boolean), GetType(TBx), New PropertyMetadata(New PropertyChangedCallback(AddressOf IsNewRecordChanged)))
Public Property IsNewRecord As Boolean
Get
Return GetValue(IsNewRecordProperty)
End Get
Set(value As Boolean)
SetValue(IsNewRecordProperty, value)
End Set
End Property
Protected Overrides Sub OnInitialized(e As System.EventArgs)
MyBase.OnInitialized(e)
VerticalAlignment = Windows.VerticalAlignment.Center
HorizontalAlignment = Windows.HorizontalAlignment.Left
BorderBrush = New SolidColorBrush(Colors.Silver)
Height = 22
SpellCheck.IsEnabled = True
UndoLimit = 0
If IsNewRecord = True Then
BorderThickness = New Thickness(1)
IsReadOnly = False
Background = New SolidColorBrush(Colors.White)
Else
BorderThickness = New Thickness(0)
IsReadOnly = True
Background = New SolidColorBrush(Colors.Transparent)
End If
End Sub
Private Shared Sub IsNewRecordChanged(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim vControl As TBx = TryCast(sender, TBx)
Dim vBoolean As Boolean = e.NewValue
If vBoolean = True Then
vControl.BorderThickness = New Thickness(1)
vControl.IsReadOnly = False
vControl.Background = New SolidColorBrush(Colors.White)
Else
vControl.BorderThickness = New Thickness(0)
vControl.IsReadOnly = True
vControl.Background = New SolidColorBrush(Colors.Transparent)
End If
End Sub
End Class
Thank you
Couldn't find an easy way to do this from the class, but this works on the page
Dim CP As New ContentPresenter
CP.RecognizesAccessKey = False
Then add the TextBox to the ContentPresenter
Case 1
vLabel.Text = "Page Name"
With vTB
.Width = 200
.Name = vName & "PageNameTB"
.ToolTip = "This is the short name for the page"
.IsNewRecord = IsNewRecord
End With
CP.Content = vTB
The add the CP to the grid
RegisterControl(SecurePage_Grid, vTB)
Grid.SetColumn(vLabel, 0)
Grid.SetRow(vLabel, i)
If i = 1 Then
Grid.SetRow(CP, i)
Grid.SetColumn(CP, 1)
Else
Grid.SetRow(vTB, i)
Grid.SetColumn(vTB, 1)
End If
vGrid.Children.Add(vLabel)
If i = 1 Then
vGrid.Children.Add(CP)
Else
vGrid.Children.Add(vTB)
End If
Related
I have a ListBox that I fill with custom objects, these objects have the following properties as seen below:
Public Class VariableClass
Public Property Content As String
Public Property myNameLabel As New Label
Public Property myNameTextBox As New ComboBox
Public Property myTypeLabel As New Label
Public Property myTypeTextBox As New ComboBox
Public Overrides Function ToString() As String
Return Content.ToString()
End Function
End Class
When the user clicks on any of the custom objects, the properties of the custom objects that are WPF controls are pragmatically created in a stackpanel.
I do it like this:
If Flowchart.SelectedItem.GetType.Name = "VariableClass" Then
SetLabelProperties(Flowchart.SelectedItem.myNameLabel, "Name:", "25", LabelPanel.Width, HorizontalAlignment.Center)
SetLabelProperties(Flowchart.SelectedItem.myTypeLabel, "Type:", "25", LabelPanel.Width, HorizontalAlignment.Center)
SetComboBoxProperties(Flowchart.SelectedItem.myNameTextBox, Flowchart.SelectedItem.myNameTextBox.Text, "25", ValuePanel.Width, VerticalContentAlignment.Center, True, True)
SetComboBoxProperties(Flowchart.SelectedItem.myTypeTextBox, Flowchart.SelectedItem.myTypeTextBox.Text, "25", ValuePanel.Width, VerticalContentAlignment.Center, True, True)
AddPropertiesInStackPanel(Flowchart.SelectedItem)
End if
The functions:
Function SetLabelProperties(myLabel As Label, myName As String, myHeight As String, myWidth As String, myHorizontalAlignment As HorizontalAlignment)
myLabel.Content = myName
myLabel.Height = myHeight
myLabel.Width = myWidth
myLabel.HorizontalContentAlignment = myHorizontalAlignment
End Function
Function SetComboBoxProperties(myComboBox As ComboBox, myName As String, myHeight As String, myWidth As String, myVerticalAlignment As VerticalAlignment, Editable As Boolean, SearchEnabled As Boolean)
myComboBox.IsEditable = Editable
myComboBox.IsTextSearchEnabled = SearchEnabled
myComboBox.Text = myName
myComboBox.Height = myHeight
myComboBox.Width = myWidth
myComboBox.VerticalContentAlignment = myVerticalAlignment
Dim myDouble As Double = 0
Dim myStatic As ResourceKey = SystemParameters.VerticalScrollBarWidthKey
myComboBox.Resources.Add(myStatic, myDouble)
End Function
Function SetTextBoxProperties(myTextBox As TextBox, myName As String, myHeight As String, myWidth As String, myVerticalAlignment As VerticalAlignment)
myTextBox.Text = myName
myTextBox.Height = myHeight
myTextBox.Width = myWidth
myTextBox.VerticalContentAlignment = myVerticalAlignment
End Function
Function AddPropertiesInStackPanel(myObject As Object)
Dim info() As PropertyInfo = myObject.GetType().GetProperties()
For Each item In info
Dim myElementSplit = Split(item.PropertyType.FullName, ".")(UBound(Split(item.PropertyType.FullName, ".")))
If myElementSplit = "Label" Then
LabelPanel.Children.Add(item.GetValue(myObject))
LabelPanel.Children.Add(New Separator With {.Height = 1, .Opacity = 0})
ElseIf myElementSplit = "ComboBox" Then
ValuePanel.Children.Add(item.GetValue(myObject))
ValuePanel.Children.Add(New Separator With {.Height = 1, .Opacity = 0})
ElseIf myElementSplit = "TextBox" Then
ValuePanel.Children.Add(item.GetValue(myObject))
ValuePanel.Children.Add(New Separator With {.Height = 1, .Opacity = 0})
End If
Next
End Function
I have tried this event that triggers whenever the user types into a ComboBox in the stackpanel.
Private Sub ValuePanel_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles ValuePanel.PreviewKeyDown
Dim myElement = e.OriginalSource
Dim myVar = GetValue(myElement).GetType().GetProperty("PropertyName")
End Sub
But myElement is not a DependencyProperty and it cannot be cast to one.
The control that raises the PreviewKeyDown doesn't know which propery of your custom object it "came" from. You can however store this information in the Tag property of the control, e.g.:
myNameTextBox.Tag = "myNameLabel"
...and then retrieve it in the event handler using this property:
Private Sub ValuePanel_PreviewKeyDown(sender As Object, e As KeyEventArgs)
Dim myElement = CType(e.OriginalSource, FrameworkElement)
Dim propertyName = myElement.Tag.ToString()
End Sub
As the image shown, the combo box text in my case is very long.
Without changing the width of the combo box, is there any method to show full text when the user hovers on it?
Without changing the width of the combo box, is there any method to show full text when the user hovers on it?
You can use the ToolTip component to show the items with long text when the mouse pointer hovers over the control. Whenever the SelectedIndex changes, measure the selected item by the TextRenderer.MeasureText method, and if the string's width is greater than the editbox's, set the long string as a tooltip for the control.
Note: The width of the EditBox = ComboBox.Width - ButtonWidth. You can get the ButtonWidth from the SystemInformation.VerticalScrollBarWidth property.
To apply this feature, let's create a little class and inherit the ComboBox control.
C#
// +
// using System.ComponentModel;
[DesignerCategory("Code")]
public class ComboBoxEx : ComboBox
{
private readonly ToolTip ttp;
public ComboBoxEx() : base() => ttp = new ToolTip();
private bool _showItemToolTip = true;
[DefaultValue(true)]
public bool ShowItemToolTip
{
get => _showItemToolTip;
set
{
if (_showItemToolTip != value)
{
_showItemToolTip = value;
ttp.SetToolTip(this, string.Empty);
}
}
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
if (ShowItemToolTip)
{
string str = string.Empty;
if (SelectedIndex >= 0)
{
var sz = TextRenderer.MeasureText(Text, Font);
if (sz.Width > Width - SystemInformation.VerticalScrollBarWidth)
str = Text;
}
ttp.SetToolTip(this, str);
}
}
protected override void Dispose(bool disposing)
{
if (disposing) ttp.Dispose();
base.Dispose(disposing);
}
}
VB.Net
' +
' Imports System.ComponentModel
<DesignerCategory("Code")>
Public Class ComboBoxEx
Inherits ComboBox
Private ReadOnly ttp As ToolTip
Sub New()
MyBase.New
ttp = New ToolTip()
End Sub
Private _showItemToolTip As Boolean = True
<DefaultValue(True)>
Public Property ShowItemToolTip As Boolean
Get
Return _showItemToolTip
End Get
Set(value As Boolean)
If (_showItemToolTip <> value) Then
_showItemToolTip = value
ttp.SetToolTip(Me, String.Empty)
End If
End Set
End Property
Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)
MyBase.OnSelectedIndexChanged(e)
If ShowItemToolTip Then
Dim str = ""
If SelectedIndex >= 0 Then
Dim sz = TextRenderer.MeasureText(Text, Font)
If sz.Width > Width - SystemInformation.VerticalScrollBarWidth Then
str = Text
End If
End If
ttp.SetToolTip(Me, str)
End If
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing Then ttp.Dispose()
MyBase.Dispose(disposing)
End Sub
End Class
You can use the same approach if you don't want to subclass. Drop a ToolTip component and handle the ComboBox.SelectedIndexChanged event as shown above.
I have a Winforms app with two ListViews in a SplitContainer.
When I drag the splitter to hide part of the Panel2 ListView items, it automatically adds a vertical scrollbar.
When I drag the splitter to hide part of the Panel1 ListView items, it does not add a vertical scrollbar.
Changing which ListView is in which Panel has the same behavior. It's as if something about the SplitContainer or its panels is controlling whether the vertical scrollbar is added to the ListView in Panel1 or not. How to make whichever ListView is in the top Panel1 also automatically add the vertical scrollbar?
To replicate, create a simple Winforms application with one form. Here is my form code followed by the designer form code.
Public Class Form1
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Try
Timer1.Enabled = False
TechDateList.BeginUpdate()
TechDateList.Items.Clear()
StopsList.BeginUpdate()
StopsList.Items.Clear()
For i As Integer = 1 To 5
Dim techItem = New ListViewItem
techItem.UseItemStyleForSubItems = False
techItem.SubItems(0).Text = Date.Now.ToString("MMM dd, yyyy")
techItem.SubItems.Add(String.Format("Tech {0}", i))
TechDateList.Items.Add(techItem)
Next
For i As Integer = 1 To 5
Dim stopItem = New ListViewItem
stopItem.UseItemStyleForSubItems = False
stopItem.SubItems(0).Text = Choose(i, "AAA", "BBB", "CCC", "DDD", "EEE")
stopItem.SubItems.Add(String.Format("Stop {0}", i))
StopsList.Items.Add(stopItem)
Next
Catch ex As Exception
MsgBox(ex.ToString(), MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Timer1_Tick Error 1")
Finally
TechDateList.EndUpdate()
StopsList.EndUpdate()
End Try
Try
ListSplitter.Panel1Collapsed = False
ListSplitter.SplitterDistance = 125
ListSplitter.SplitterWidth = 6
TechDateList.Items.Item(0).Selected = True
Catch ex As Exception
MsgBox(ex.ToString(), MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Timer1_Tick Error 2")
End Try
End Sub
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.ListSplitter = New System.Windows.Forms.SplitContainer()
Me.TechDateList = New System.Windows.Forms.ListView()
Me.UInitial = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.SchedDate = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.StopsList = New System.Windows.Forms.ListView()
Me.StopNum = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.StopName = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
CType(Me.ListSplitter, System.ComponentModel.ISupportInitialize).BeginInit()
Me.ListSplitter.Panel1.SuspendLayout()
Me.ListSplitter.Panel2.SuspendLayout()
Me.ListSplitter.SuspendLayout()
Me.SuspendLayout()
'
'ListSplitter
'
Me.ListSplitter.Dock = System.Windows.Forms.DockStyle.Fill
Me.ListSplitter.FixedPanel = System.Windows.Forms.FixedPanel.Panel1
Me.ListSplitter.Location = New System.Drawing.Point(0, 0)
Me.ListSplitter.Name = "ListSplitter"
Me.ListSplitter.Orientation = System.Windows.Forms.Orientation.Horizontal
'
'ListSplitter.Panel1
'
Me.ListSplitter.Panel1.Controls.Add(Me.TechDateList)
Me.ListSplitter.Panel1Collapsed = True
Me.ListSplitter.Panel1MinSize = 0
'
'ListSplitter.Panel2
'
Me.ListSplitter.Panel2.Controls.Add(Me.StopsList)
Me.ListSplitter.Size = New System.Drawing.Size(384, 261)
Me.ListSplitter.SplitterDistance = 25
Me.ListSplitter.SplitterWidth = 1
Me.ListSplitter.TabIndex = 1
'
'TechDateList
'
Me.TechDateList.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.TechDateList.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.UInitial, Me.SchedDate})
Me.TechDateList.FullRowSelect = True
Me.TechDateList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.TechDateList.HideSelection = False
Me.TechDateList.LabelWrap = False
Me.TechDateList.Location = New System.Drawing.Point(4, 0)
Me.TechDateList.Margin = New System.Windows.Forms.Padding(0)
Me.TechDateList.MultiSelect = False
Me.TechDateList.Name = "TechDateList"
Me.TechDateList.ShowGroups = False
Me.TechDateList.Size = New System.Drawing.Size(258, 166)
Me.TechDateList.TabIndex = 0
Me.TechDateList.UseCompatibleStateImageBehavior = False
Me.TechDateList.View = System.Windows.Forms.View.Details
'
'UInitial
'
Me.UInitial.Text = "Route"
Me.UInitial.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.UInitial.Width = 100
'
'SchedDate
'
Me.SchedDate.Text = "Job Date"
Me.SchedDate.Width = 133
'
'StopsList
'
Me.StopsList.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.StopsList.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.StopNum, Me.StopName})
Me.StopsList.FullRowSelect = True
Me.StopsList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.StopsList.HideSelection = False
Me.StopsList.LabelWrap = False
Me.StopsList.Location = New System.Drawing.Point(4, 0)
Me.StopsList.Margin = New System.Windows.Forms.Padding(0)
Me.StopsList.MultiSelect = False
Me.StopsList.Name = "StopsList"
Me.StopsList.ShowGroups = False
Me.StopsList.Size = New System.Drawing.Size(258, 252)
Me.StopsList.TabIndex = 0
Me.StopsList.UseCompatibleStateImageBehavior = False
Me.StopsList.View = System.Windows.Forms.View.Details
'
'StopNum
'
Me.StopNum.Text = "000"
Me.StopNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.StopNum.Width = 34
'
'StopName
'
Me.StopName.Text = "Stop Name"
Me.StopName.Width = 199
'
'Timer1
'
Me.Timer1.Interval = 250
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(384, 261)
Me.Controls.Add(Me.ListSplitter)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ListSplitter.Panel1.ResumeLayout(False)
Me.ListSplitter.Panel2.ResumeLayout(False)
CType(Me.ListSplitter, System.ComponentModel.ISupportInitialize).EndInit()
Me.ListSplitter.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Friend WithEvents ListSplitter As SplitContainer
Friend WithEvents TechDateList As ListView
Friend WithEvents UInitial As ColumnHeader
Friend WithEvents SchedDate As ColumnHeader
Friend WithEvents StopsList As ListView
Friend WithEvents StopNum As ColumnHeader
Friend WithEvents StopName As ColumnHeader
Friend WithEvents Timer1 As Timer
End Class
From what I see in Designer code, TechDateList Height exceeds ListSplitter.Panel1 Height:
Me.ListSplitter.SplitterDistance = 25
Me.TechDateList.Size = New System.Drawing.Size(258, 166)
make sure that TechDateList fits Panel1 in Designer, e.g
Me.ListSplitter.SplitterDistance = 125
Me.TechDateList.Size = New System.Drawing.Size(258, 120)
and then resize will work as expected.
consider also docking TechDateList to Left - the list will get maximum possible Height and will resize with Panel1
I'm guessing that moving the splitter is resizing the ListView in Panel2 but not resizing the ListView in Panel1. I'm probably missing something simple somewhere. Regardless, if I add this code to the form, I get the desired results:
Private Sub ListSplitter_SplitterMoved(sender As Object, e As SplitterEventArgs) Handles ListSplitter.SplitterMoved
TechDateList.Height = ListSplitter.Panel1.Height
End Sub
I need to show ToolTip on a certain control for a certain period of time, with this code I get the ToolTip to show, but it won't disappear:
Public Sub tooltipControl(ByVal kontrola As Object, ByVal opened As Boolean, ByVal Optional poruka As String = "", ByVal Optional boja As Object = Nothing)
Dim ellipse1 As New Ellipse
ellipse1.Height = 25
ellipse1.Width = 50
ellipse1.Fill = Brushes.Gray
ellipse1.HorizontalAlignment = HorizontalAlignment.Left
Dim bubble As New ToolTip
bubble.PlacementTarget = kontrola
bubble.Placement = PlacementMode.Bottom
ToolTipService.SetShowDuration(kontrola, 5000)
Dim bdec As New BulletDecorator
Dim littleEllipse As New Ellipse
littleEllipse.Height = 20
littleEllipse.Width = 20
littleEllipse.Fill = boja
bdec.Bullet = littleEllipse
Dim tipText As New TextBlock
tipText.Text = poruka
bdec.Child = tipText
bubble.Content = bdec
bubble.IsOpen = True
kontrola.ToolTip = bubble
End Sub
Set the duration on the elemtent the tooltip belongs to
ToolTipService.SetShowDuration(kontrola, 5000)
and add the tooltip before opening it
kontrola.ToolTip = bubble
bubble.IsOpen = True
In a WPF project, using the following code to customize a button in the Window_Loaded event:
Dim style As Style = New Style
style.TargetType = GetType(Button)
Dim trigger As DataTrigger = New DataTrigger
trigger.Value = "OK"
'set binding
Dim bi As New Binding
Dim pp As New PropertyPath("Content")
bi.Path = pp
bi.RelativeSource = RelativeSource.Self
trigger.Binding = bi ' New Binding(pp.Path)
Dim setter As Setter = New Setter
setter.Property = Button.BackgroundProperty
setter.Value = Brushes.Red
trigger.Setters.Add(setter)
'clear the triggers
style.Triggers.Clear()
style.Triggers.Add(trigger)
btn_Step.Style = style
It compiles okay, but no noticeable change to the button. How can I get this to be applied?
I figured out how to do it with code - here's my final solution:
Public Function CreateStyle(ByVal clr1 As SolidColorBrush, ByVal clr2 As SolidColorBrush)
Dim st As New Style
st.TargetType = GetType(Button)
Dim se0 As New Setter
se0.Property = Button.OverridesDefaultStyleProperty
se0.Value = True
st.Setters.Add(se0)
Dim se1 As New Setter
se1.Property = TemplateProperty
Dim ct As New ControlTemplate
'Reference: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ddb7fd77-dea1-40f5-a5b7-30d35ecda70e/creating-a-control-template-with-code-behind?forum=wpf
ct.TargetType = GetType(Button)
Dim fef0 As New FrameworkElementFactory(GetType(Border))
fef0.Name = "Border"
fef0.SetValue(Border.BorderThicknessProperty, New Thickness(1))
fef0.SetValue(Border.BorderBrushProperty, Brushes.Black)
ct.VisualTree = fef0
Dim fef1 As New FrameworkElementFactory(GetType(ContentPresenter))
fef1.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center)
fef1.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center)
fef0.AppendChild(fef1)
Dim tr0 As New Trigger
tr0.Property = Button.IsMouseOverProperty
tr0.Value = True
Dim se2 As New Setter
se2.TargetName = "Border"
se2.Property = Button.BackgroundProperty
se2.Value = clr1
tr0.Setters.Add(se2)
ct.Triggers.Add(tr0)
Dim tr1 As New Trigger
tr1.Property = Button.IsMouseOverProperty
tr1.Value = False
Dim se3 As New Setter
se3.TargetName = "Border"
se3.Property = Button.BackgroundProperty
se3.Value = clr2
tr1.Setters.Add(se3)
ct.Triggers.Add(tr1)
se1.Value = ct
st.Setters.Add(se1)
Return st
End Function