FocusVisualStyle In RadioButton not Work - wpf

This is not working for me, focus on radio button only works when pressed the Tab key! Does anyone know how to fix?
void SelectPaymentModeView_Loaded(object sender, RoutedEventArgs e)
{
this.radPaymentMode.Focus();
}
The contents of the radiobutton is text... I also try Keyboard.Focus(this.radPaymentMode);
See the complete code:
PaymentMode[] modes = data[1] as PaymentMode[];
if (modes.Length > 0)
{
for (int i = 0; i < modes.Length; i++)
{
RadioButton rad = new RadioButton();
rad.Name = "radPayment" + i;
rad.GroupName = "PaymentModes";
rad.Content = modes[i].Name;
rad.DataContext = modes[i];
rad.Margin = new Thickness(110, 0, 0, 5);
rad.VerticalAlignment = System.Windows.VerticalAlignment.Center;
rad.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
Grid.SetRow(rad, 3 + i);
Grid.SetColumn(rad, 1);
gridPaymentModes.RowDefinitions.Insert(3, new RowDefinition());
gridPaymentModes.Children.Add(rad);
radPaymentModes.Add(rad);
if (!string.IsNullOrEmpty((this.DataContext as Order).Payment))
{
String paymentOrder = rad.Content as String;
if (paymentOrder.Equals((this.DataContext as Order).Payment))
{
rad.IsChecked = true;
}
}
rad.Checked += new RoutedEventHandler(rad_Checked);
}
radPaymentModes[0].Loaded += SelectPaymentModeView_Loaded;
}
void SelectPaymentModeView_Loaded(object sender, RoutedEventArgs e)
{
FocusManager.SetFocusedElement(FocusManager.GetFocusScope((sender as RadioButton)), (sender as RadioButton));
}

The keyboard focus manager makes the dotted focus adorner visible when the keyboard is used to tab to a control (WPF wants to hide the focus rect when the mouse is used for example so there's less visual clutter).
To force it, use code like this (assuming btnRadio is your button):
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(btnRadio), btnRadio);

Related

How do I call a control that was created dynamically in c#

First, a great thank you to those who asked/responded to questions. You were able to get me this far.
I wanted to help a young Belgian entrepreneur by taking on a challenge, build a Media managing software to display various media types (Images, Videos, links, text) on huge LED screens.
I have limited coding experience as I work in EDI.
My issue is that I create playlists dynamically based on the number of playlists in the DB (see screenshot), but I cannot trigger the playing of the right playlist when pressing the play button.
Warning, my code is noob code.
PlayList ScreenShot
Label playListLbl = new Label();
GroupBox playListGrp = new GroupBox();
public GroupBox addplayListGrp(int i, int start, int end)
{
GroupBox playListGrp = new GroupBox();
playListGrp.Name = "playListGrp"+ Convert.ToString(1 + i);
playListGrp.Text = "Play list " + Convert.ToString(1 + i);
playListGrp.Font = new Font("Century Gothic", 12F,
FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
playListGrp.Width = 425;
playListGrp.Height = 525;
playListGrp.Margin = new Padding(1);
playListGrp.Location = new Point(start, end);
return playListGrp;
}
Button addPlayBtn(int i)
{
Button PlayBtn = new Button();
PlayBtn.Font = new Font("Century Gothic", 9.75F,
System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((byte)(0)));
PlayBtn.ForeColor = Color.Black;
PlayBtn.Location = new Point(10, 467);
PlayBtn.Name = "playBtn" + Convert.ToString(1 + i);
PlayBtn.Size = new Size(100, 30);
PlayBtn.TabIndex = 6;
PlayBtn.Text = "Play";
PlayBtn.UseVisualStyleBackColor = true;
PlayBtn.Click += new EventHandler(playBtn1_Click);
return PlayBtn;
}
public BMS_main()
{
int startPos = 5;
int endPos = 5;
for (int i = 1; i <= playlistCountInc; i++)
{
playListGrp = addplayListGrp(i, startPos, endPos);
playListLbl = addLabel(i);
Label playListLblTime = addLabelTime(i);
Button PlayBtn = addPlayBtn(i);
}
playListGrp.Controls.Add(playListLbl);
playListGrp.Controls.Add(playListLblTime);
playListGrp.Controls.Add(playlistView);
playListGrp.Controls.Add(PlayBtn);
}
private void playBtn1_Click(object sender, EventArgs e)
{
if (ScreenStatus)
{
Playing = true;
DisplayTimer.Stop();
DisplayTimer.Enabled = false;
InitialScreenTimer.Stop();
InitialScreenTimer.Enabled = false;
PlayListTimer.Enabled = true;
PlayListTimer.Start();
}
else
{
message = "Veuillez alimenter les panneaux";
result = MessageBox.Show(message, caption, buttons);
}
public void PlayListTimer_Tick(object sender, EventArgs e)
{
Label lblAcessorio4 =
(Label)playListLbl.Controls.Find("playLbl4",
true).FirstOrDefault();
if (lblAcessorio4 != null)
{
lblAcessorio4.Text = "Test lblAcessorio4";
}
else
{
message = "Label is null";
result = MessageBox.Show(message, caption, buttons);
}
Set the Tag property of your button with something which will help you decide later on which song to play:
playListGrp = addplayListGrp(i, startPos, endPos);
playListLbl = addLabel(i);
Label playListLblTime = addLabelTime(i);
Button PlayBtn = addPlayBtn(i);
// You can do this
PlayBtn.Tag = playListGrp; // or anything else
Then in the button click handler, get the value of the Tag and make a decision based on that. Just keep in mind that whatever you set the Tag to, you will need to cast it back to that type. For example, in the above I set it GroupBox so I will cast it to a GroupBox:
private void playBtn1_Click(object sender, EventArgs e)
{
GroupBox gb = ((Button)(sender)).Tag as GroupBox;
// Now make the decision
if(gb.Name == "whatever you need to put here"){ // do whatever }
}
I would put the lisbox and then get the selected item and play that.

DataGridView Custom control enable button in Unedited mode

Does anyone know how to get the button visible all the time?.(Not only in edit mode of the cell)
I would like to take your attention to the answer of this question.
how to add ellipse button and textbox in current cell of datagridview in winforms
I could enhance this solution to see the button control in the cell for all the time. What I want is to get the popup box for the first click of the cell. This is the code to paint the button in uneditted mode.
// Finally paint the NumericUpDown control
Rectangle srcRect = new Rectangle(0, 0, valBounds.Width, valBounds.Height);
if (srcRect.Width > 0 && srcRect.Height > 0)
{
Bitmap renderingBitmap = new Bitmap(22, 18);
new TextButton().button.DrawToBitmap(renderingBitmap, srcRect);
graphics.DrawImage(renderingBitmap, new Rectangle(new Point(cellBounds.X+cellBounds.Width-24, valBounds.Location.Y-2), valBounds.Size),
srcRect, GraphicsUnit.Pixel);
}
A better option would be to embed a button on your DataGridView. This would give you more control over the use of DataGridView. See the following snippet:
Button b1 = new Button();
int cRow = 0, cCol = 0;
private void Form1_Load(object sender, EventArgs e)
{
b1.Text = "...";
b1.Visible = false;
this.dataGridView1.Controls.Add(b1);
b1.BringToFront();
this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);
this.b1.Click += new EventHandler(b1_Click);
}
void b1_Click(object sender, EventArgs e)
{
//Implement your logic here
}
void dataGridView1_Paint(object sender, PaintEventArgs e)
{
if(cRow != 0 && cCol != 0)
{
Rectangle rect = new Rectangle();
rect = dataGridView1.GetCellDisplayRectangle(cRow ,cCol , false);
rect.X = rect.X + (2*dataGridView1.Columns[1].Width / 3);
rect.Width = dataGridView1.Columns[1].Width / 3;
b1.Bounds = rect;
b1.Visible = true;
}
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
cRow = e.RowIndex;
cCol = e.ColumnIndex;
}
In the above snippet the location of ellipses button is set to last clicked cell. The visibility is always true after a cell is clicked. In my opinion this would provide a far better control over the button's function,and is easier to maintain.

Resizing a form introduces visual artifacts on bottom docked controls

I am working on a "bottom-right docked" popup form.
The layout of the form follows this structure:
Header
Content (text message)
Footer
This form should resize according to its content.
I am using SetBounds to make it grow to the top instead of the bottom (remember that the window is docked bottom-right).
However, when the animation occurs, the footer redraws itself in a very bad way, as its form-relative location is continuously updated.
I provide a sample to give you an idea:
using System.Windows.Forms;
namespace AnimatorTest
{
public class Form3 : Form
{
Timer timer = new Timer();
public Form3()
{
timer.Interval = 30;
timer.Tick += timer_Tick;
// Create 3 test buttons
for (int i = 0; i < 3; i++)
{
Button b = new Button() { Dock = DockStyle.Bottom };
b.Click += (s, e) => timer.Start();
b.Text = "Click and watch how ugly I am during the animation.";
Controls.Add(b);
}
Height = 100;
StartPosition = FormStartPosition.CenterScreen;
}
void timer_Tick(object sender, System.EventArgs e)
{
int desiredHeight = 500;
int difference = desiredHeight - Height;
int change = difference / 6;
if (System.Math.Abs(change) < 1)
{
SetBounds(Left, Top - difference, Width, Height + difference);
timer.Stop();
}
else
{
SetBounds(Left, Top - change, Width, Height + change);
}
}
}
}
I don't really have any idea to work around this.
Thanks.

DataGrid select last cell programmatically

When the DataGrid below gets the focus for the first time and only the first time (ie, after some other control has had the focus), the last row, 2nd column should be focused and in edit.
I added a handler for the DataGrid.GotFocus, but it's complicated code and not getting the result above.
Anyone got an elegant, bullet proof solution?
I made tiny modifications to the code
the sender should always be the grid I want, so I just used that instead of relying on a name
When the SelectionUnit is FullRow, as my grid was before I changed it to CellOrRowHeader you
apparently can't call SelectedCells.Clear()
Code below:
private void OnDataGridKeyboardGotFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var dg = sender as DataGrid;
if (_hasHadInitialFocus) return;
var rowIndex = dg.Items.Count - 2;
if (rowIndex >= 0 && dg.Columns.Count - 1 >= 0)
{
var column = dg.Columns[dg.Columns.Count - 1];
var item = dg.Items[rowIndex];
var dataGridCellInfo = new DataGridCellInfo(item, column);
if (dg.SelectionUnit != DataGridSelectionUnit.FullRow) {
dg.SelectedCells.Clear();
dg.SelectedCells.Add(dataGridCellInfo);
}
else {
var row = dg.GetRow(rowIndex);
row.IsSelected = true;
}
dg.CurrentCell = dataGridCellInfo;
dg.BeginEdit();
}
_hasHadInitialFocus = true;
}
New Question
I want to repeat the selection when the focus goes to another control in the window and then back to the grid.
I thought I could turn that _hasHadInitialFocus latch to false in a LostFocus event, but the code below is firing on cell changes.
Do you know how I should be trapping the lost focus event better, and do you agree that is the place to turn the latch off?
private void DataGridLostFocus(object sender, RoutedEventArgs e) {
_hasHadInitialFocus = false;
}
You may have to fiddle with the offsets depending on whether there's an new item row visible or not, but this works for me.
private bool _hasHadInitialFocus;
private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (!_hasHadInitialFocus)
{
if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
{
var dataGridCellInfo = new DataGridCellInfo(
dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);
dataGrid.SelectedCells.Clear();
dataGrid.SelectedCells.Add(dataGridCellInfo);
dataGrid.CurrentCell = dataGridCellInfo;
dataGrid.BeginEdit();
}
_hasHadInitialFocus = true;
}
}
I noticed that clicking into the grid leaves one cell selected and the target cell in edit mode. A solution to this if required is:
private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
EditCell();
}
private void PreviewMouseLBDown(object sender, MouseButtonEventArgs e)
{
if (!_hasHadInitialFocus)
{
e.Handled = true;
EditCell();
}
}
private void EditCell()
{
if (!_hasHadInitialFocus)
{
if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
{
var dataGridCellInfo = new DataGridCellInfo(
dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);
dataGrid.SelectedCells.Clear();
dataGrid.SelectedCells.Add(dataGridCellInfo);
dataGrid.CurrentCell = dataGridCellInfo;
dataGrid.BeginEdit();
}
_hasHadInitialFocus = true;
}
}

Add WPF control at runtime

I've written a WPF UserControl, and want to add one or more of it to my Window at runtime when I click a button. How can I do that?
Edit: Further specification
I want to add the usercontrols to a Canvas, and put in a absolute position. The canvas is a drawing of the floors in my house, and each usercontrol has properties to indicate where in the house it is positioned. So I want all the controls to be positioned in the correct position on the canvas.
I'm thinking something like this
var light = new LightUserControl(2);
HouseCanvas.Children.Add(light); // this should be positioned in a specific place
After you add the your control to the Canvas you need to specify the top and left co-ordinates using the Canvas.Top and Canvas.Left attached properties as follows.
var light = new LightUserControl(2);
HouseCanvas.Children.Add(light);
Canvas.SetLeft(light, 20);
Canvas.SetTop(light, 20);
In case you want to add the control to a Grid instead of a Canvas you can specify all the Grid properties through the Grid static class as follows:
Label newLabel = new Label();
newLabel.Content = "The New Element";
Main.Children.Add(newLabel);
Grid.SetColumn(newLabel, 0);
Grid.SetRow(newLabel, 0);
Add a StackPanel to the window and on each button click,
_stackPanel.Children.Add(new YourControl());
You can do this in many ways.
My solution:
for (i = 1; i <= buttoncount; i++)
{
Button mybutton = new Button();
Grid1.Children.Add(mybutton);
mybutton.Height = 100;
mybutton.Width = 100;
mybutton.Name = "button" + i;
mybutton.Content = mybutton.Name;
}
public static void AddChild(this Visual parent, UIElement child)
{
if (InternalAddChild(parent, child))
{
return;
}
throw new NotSupportedException();
}
private static bool InternalAddChild(Visual parent, UIElement child)
{
Panel panel = parent as Panel;
if (panel != null)
{
panel.Children.Add(child);
return true;
}
for (int i = VisualTreeHelper.GetChildrenCount(parent) - 1; i != -1; i--)
{
Visual target = VisualTreeHelper.GetChild(parent, i) as Visual;
if (target != null && InternalAddChild(target, child))
{
return true;
}
}
return false;
}
Just complementing the answer:
for (i = 1; i <= buttoncount; i++)
{
Button mybutton = new Button();
Grid1.Children.Add(mybutton);
mybutton.Height = 100;
mybutton.Width = 100;
mybutton.Name = "button" + i;
mybutton.Content = mybutton.Name;
mybutton.Click += button_Click;
}
private void button_Click(object sender, RoutedEventArgs e)
{
// do something
}

Resources