WPF Xceed PropertyGrid change background - wpf

I have to define a property grid only in code behind
Xceed.Wpf.Toolkit.PropertyGrid.PropertyGrid m_PropertyGrid;
Then I want to be able to customize it according to the selected object.
So I define the event
private void M_PropertyGrid_SelectedObjectChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
foreach (Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem item in (sender as Xceed.Wpf.Toolkit.PropertyGrid.PropertyGrid).Properties)
{
item.Background = new SolidColorBrush(Colors.Green);
item.Foreground = new SolidColorBrush(Colors.Red);
item.BorderBrush = new SolidColorBrush(Colors.Orange);
item.BorderThickness = new Thickness(3);
}
}
but the effect is the following
it seems that the effect is only on the first column and not the second one.
what's more I can't change the effect on enums so when a combo opens the effect is unreadable
thank you for any help

Related

Find control that caused ContextMenuStrip menu to be shown

I've read a few articles on SO:
How to detrmine the control that cause ContextMenuStrip
Getting the control of a context menu
and a couple others that suggested use of the SourceControl property.. but none work in this context:
I have a ContextMenuStrip that has a child ToolStripMenuItem - this code from the windows forms designer generated section:
// _tileContextMenuStrip
//
this._tileContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tileKindToolStripMenuItem,
this.forceWidthScalingToolStripMenuItem,
this.forceHeightScalingToolStripMenuItem});
this._tileContextMenuStrip.Name = "_tileContextMenuStrip";
this._tileContextMenuStrip.Size = new System.Drawing.Size(184, 70);
//
// tileKindToolStripMenuItem
//
this.tileKindToolStripMenuItem.Name = "tileKindToolStripMenuItem";
this.tileKindToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
this.tileKindToolStripMenuItem.Text = "Tile Kind";
So the context menu strip and the menu item first in the list are fixed at design time. At runtime, the TSMI has child TSMIs added to it in a loop based on an enum:
foreach(TileKind t in typeof(TileKind).GetEnumValues()) {
ToolStripMenuItem tsmi = new ToolStripMenuItem(t.ToString("g"));
tsmi.Tag = t;
tsmi.Click += tsmi_Click;
tileKindToolStripMenuItem.DropDownItems.Add(tsmi);
}
Later I have 20 checkboxes on my form and I set their .ContextMenuStrip to be the same thing:
foreach(Thing t in someDataSource){
CheckBox c = new CheckBox();
c.Text = t.SomeData;
c.ContextMenuStrip = this._tileContextMenuStrip;
myPanelBlah.Controls.Add(c);
}
Great, so now I have all my checkboxes and they all show the context menu when I right click them, but when I choose one the sub-menu items, I just can't find out the control that fired the context menu...
//this the click handler for all the menu items dynamically added
void tsmi_Click(object sender, EventArgs e)
{
ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
(tsmi.OwnerItem //the parent node in the menu tree hierarchy
.Owner as ContextMenuStrip) //it's a ContextMenuStrip so the cast succeeds
.SourceControl //it's always null :(
}
I can reliably get ahold of the contextmenustrip either by routing up from the event handler sender, or even just by referencing the ContextMenuStrip itself as a form instance variable, but SourceControl is always null
Any ideas what to try next?
I see the problem, quacks loudly like a bug. There's a workaround, you can subscribe the ContextMenuStrip's Opening event. At that point, well before you start navigating into the sub-items, the SourceControl property is still valid. So store it in a field of the class so you'll have it available in the Click event handler. Roughly:
private Control _tileCmsSource;
private void _tileContextMenuStrip_Opening(object sender, CancelEventArgs e) {
_tileCmsSource = _tileContextMenuStrip.SourceControl;
}
void tsmi_Click(object sender, EventArgs e)
{
ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
// Use _tileCmsSource here
//...
}

Add a new row to DataGrid at runtime (WPF)

I have a DataGrid and fill it when window loaded, like this:
private void Window_Loaded(object sender, RoutedEventArgs e) {
var list = DbService.GetStuffsFull();
dataGrid.ItemsSource = list;
}
and when i try to add a new row at run-time by this code:
Stuff item = new Stuff();
dataGrid.Items.Add(item);
I get this error:
Operation is not valid while
ItemsSource is in use. Access and
modify elements with
ItemsControl.ItemsSource instead.
how can I add a new row at runtime?
You cannot modify items in Items collection if you provided it as ItemsSource. You should either add item to your list (with INotifyCollectionChanged implemented or you should initially populated Items property via Add method.
The error description is pretty clear, isn't it?
try doing something like this:
var row = dataGrid.NewRow();
dataGrid.Rows.Add(row);
row["column1"] = "data1";
row["column2"] = "data2";
row["column3"] = "data3";
InitializeComponent();

How to auto cap a textbox

How do I make it so that when a user types letters into a textbox in silverlight that it changes these letters to all capitals? And at the same time still fires all the same events such as keypress.
If you want to avoid code behind or custom controls (preferable), this sort of functionality is available via behaviours.
e.g. this one in the Expression blend Gallery converts any text box to which it is attached into uppercase.
Then is just a matter of drag-drop in Blend or adding the trigger manually in VS2010.
There was no easy way to do it except to use an embedded all caps font. All other ways interfered with how the textbox worked.
The simplest way would be:
private void tb_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = (TextBox)sender;
var caret = tb.CaretIndex;
tb.Text = tb.Text.ToUpper();
tb.CaretIndex = caret;
}
If you wanna save even more performance, handle the LostFocus event instead (which you then don't have to worry about carret position either):
private void tb_LostFocus(object sender, RoutedEventArgs e)
{
var tb = (TextBox)sender;
tb.Text = tb.Text.ToUpper();
}
But if the data is bound to a model/entity I would call the ToUpper() on the bound object property setter / OnPropertyChanged, OnTextChanged or whatever it is in the entity.

WPF ComboBox, force input to UpperCase

I have an editable WPF ComboBox with TextSearchEnabled. I need to force the user's text input to uppercase when they type to filter the ComboBox.
I was thinking of modifying the textbox that is part of the control (named 'PART_EditableTextBox') to set CharacterCasing="Upper", however I can't quite figure out how to do this.
Do I need to use a trigger, or modify the template in some way?
This works and seems like a reasonable solution:
protected void winSurveyScreen_Loaded(object sender, RoutedEventArgs e)
{
(comboBox.Template.FindName("PART_EditableTextBox", cbObservation) as TextBox).CharacterCasing = CharacterCasing.Upper;
}
Ensure that the combobox is not collapsed on loaded otherwise the template will not be found.
IMO, the quicker way is to set the UpdateTrigger to PropertyChanged and, in the data object, uppercase the value when it is updated.
I found that post where the attached property is used. That permit to use that for all of your ComboBox without rewriting the code.
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Textbox editableTextbox = sender as Textbox;
foreach (char ch in e.Text)
{
if (Char.IsLower(ch))
{
editableTextbox.Text += Char.ToUpper(ch);
e.Handled = true;
}
}
}
or try creating an attached behaviour for the textbox

highlight a win forms checkbox when cursor is inside it

I have a checkbox with no text specified. Now whenever I tab down to this checkbox, it doesnot get highlighted.I even tried setting focus in checkbox_Enter() event. I checked for focus in this event and focus is there in this checkbox. How to get it highlighted so that user can know that the cursor is there in checkbox.
Try putting just a space into the Checkbox
Or
setting AutoSize to false
Setting the size of the Checkbox
Then there may be somewhere for WinForms to draw the focus ret.
Otherwise you have to to custom draw the Checkbox, or draw the focus rec round the Checkbox yourself.
Whatever you do it will not look that good, as users expect the focus rec to be round the label of the checkbox, and you wish to have a checkbox with no label.
I managed to do it by the below mentioned way
Use a panel.Push the checkbox inside that panel.Set the dimensions of a panel as such that it looks like a rectangle around the checkbox.In checkbox_enter() event set the border
BorderStyle.FixedSingle;
And in checkbox_Leave() event set the border again to
BorderStyle.None;
So this way it will tell user that focus in inside the checkbox.
To make the checkbox appear highlighted I had it change color on got focus and change back on lost focus.
this part is in the Form1.Designer.cs:
private void InitializeComponent()
{...
ckBox1.GotFocus += new System.EventHandler(checkBox_Highlight);
ckBox1.LostFocus += new System.EventHandler(checkBox_EndHighlight);
ckBox1.MouseHover += new System.EventHandler(checkBox_Highlight);
ckBox1.MouseLeave += new System.EventHandler(checkBox_EndHighlight);
}
This part is in the Form1:
private void checkBox_Highlight(object sender, EventArgs e)
{
CheckBox control = (CheckBox)sender;
control.FlatStyle = FlatStyle.Flat;
control.ForeColor = Color.Blue;
}
private void checkBox_EndHighlight(object sender, EventArgs e)
{
CheckBox control = (CheckBox)sender;
if (!control.Focused)
{
control.ForeColor = DefaultForeColor;
}
}
While tabbing, this puts a light blue shadow beneath the CheckBox on Enter and on Leave - at least on my Windows7:
...
checkBox1.Enter += new System.EventHandler(check_Enter);
checkBox1.Leave += new System.EventHandler(check_Leave);
...
private void check_Enter(object sender, EventArgs e)
{
((CheckBox)sender).BackColor = SystemColors.Highlight;
}
private void check_Leave(object sender, EventArgs e)
{
((CheckBox)sender).BackColor = Color.Transparent;
}
Actually the highlights comes on the text of the checkbox not the checkbox itself
So, if I was you, I would put any control in the background of my check box and give it the focus when my checkbox is focused, to have the same look of default controls highlights.
which will be shown to end users as checkbox highlights.

Resources