How to use code-behind to create StackPanel -> Border -> Background - c#

I'm trying to set properties of a TreeViewItem -> StackPanel in c# like this question. It seems to make a lot of sense until I get to the part where I try to edit the Background in my Border. Borders have Background objects in them, but for the life of me I can't set a color or anything. It seems to be inconsistent because I can add Content to a Label by simply saying, Content = "Title".
Anyway, this is my code:
public static TreeViewItem childNode = new TreeViewItem() //Child Node
{
Header = new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
new Border {
Width = 12,
Height = 14,
Background = ? //How do I set the background?
},
new Label {
Content = "Child1"
}
}
}
};
PS - I have the same problem when trying to add a BorderBrush
Thank you!

Background property accepts an Brush. Therefore, the code can set the color as follows:
MyLabel.Background = Brushes.Aquamarine;
Or this:
SolidColorBrush myBrush = new SolidColorBrush(Colors.Red);
MyLabel.Background = myBrush;
To set any color, you can use BrushConverter:
BrushConverter MyBrush = new BrushConverter();
MyLabel.Background = (Brush)MyBrush.ConvertFrom("#ABABAB");
Setting the property to the LinearGradientBrush in code:
LinearGradientBrush myBrush = new LinearGradientBrush();
myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myBrush.GradientStops.Add(new GradientStop(Colors.Green, 0.5));
myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0));
MyLabel.Background = myBrush;
For you it would look like this:
private void Window_ContentRendered(object sender, EventArgs e)
{
TreeViewItem childNode = new TreeViewItem()
{
Header = new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
new Border
{
Width = 12,
Height = 14,
Background = Brushes.Yellow, // Set background here
},
new Label
{
Content = "Child1",
Background = Brushes.Pink, // Set background here
}
}
}
};
MyTreeView.Items.Add(childNode);
}

Related

Popup in WPF does not open

I have a datagrid with modified column header which contain a button which shall open a popup.
This is written in code behind because of different data sources with different number of columns.
That's how it looks like:
Popups are stored in:
Dictionary<string, Popup> HeaderPopups = new Dictionary<string, Popup>();
And here the code behind:
dgMaterials.AutoGeneratingColumn += (ss, ee) =>
{
Button b = new Button() { Content = "...", Name = "btn_" + ee.PropertyName, Margin = new Thickness(3) };
b.Click += HeaderFilterButtonClick;
StackPanel stackPanel = new StackPanel() { Orientation = Orientation.Horizontal };
stackPanel.Children.Add(new TextBlock() { Text = ee.PropertyName, VerticalAlignment = VerticalAlignment.Center });
stackPanel.Children.Add(b);
ee.Column.Header = stackPanel;
Popup pop = new Popup() { Name = "pop_" + ee.PropertyName, Placement = PlacementMode.Bottom, PlacementTarget = b, StaysOpen = false, Width = 200, Margin = new Thickness(3) };
Border bord = new Border() { Background = Brushes.White, BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1,1,1,1) };
pop.DataContext = bord;
HeaderPopups.Add(ee.PropertyName, pop);
StackPanel stack = new StackPanel() { Margin = new Thickness(5, 5, 5, 15) };
bord.DataContext = stack;
StackPanel stackButtons = new StackPanel() { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 15) };
Button bAll = new Button() { Margin = new Thickness(0, 0, 0, 0), Name = "btnAll_" + ee.PropertyName };
bAll.Click += btnAllClick;
TextBlock txtAll = new TextBlock() { Text = "Select All", Foreground = Brushes.Blue, Cursor = Cursors.Hand };
bAll.Content = txtAll;
Button bNone = new Button() { Margin = new Thickness(10, 0, 0, 0), Name = "btnNone_" + ee.PropertyName };
bNone.Click += btnNoneClick;
TextBlock txtNone = new TextBlock() { Text = "Select None", Foreground = Brushes.Blue, Cursor = Cursors.Hand };
bNone.Content = txtNone;
stackButtons.Children.Add(bAll);
stackButtons.Children.Add(bNone);
ListBox list = new ListBox() { Name = "lst_" + ee.PropertyName, BorderThickness = new Thickness(0) };
stack.Children.Add(stackButtons);
stack.Children.Add(list);
};
So for each column a popup is generated and I have the popups with the keys Spec_No, Grade and Class in my HeaderPopups dictionary.
I want the appropriate popups to show up beneath the clicked button, like in the example from http://www.jarloo.com/excel-like-autofilter-in-wpf/
Look here:
My problem is to open these popups in HeaderFilterButtonClick-Event. I tried it with:
private void HeaderFilterButtonClick(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
txtTest.Text += e.OriginalSource.ToString() + Environment.NewLine;
txtTest.Text += e.Source.ToString() + Environment.NewLine;
txtTest.Text += b.Name;
if (b.Name == "btn_Spec_No")
{
HeaderPopups["Spec_No"].IsOpen = true;
}
}
but it doesn't work.
Can anybody help?
Your Popup is currently empty and thus completely invisible.
You should set the Child property of it to the Border and also set the Child property of the Border to something for it to render:
Popup pop = new Popup() { ... };
Border bord = new Border() { Background = Brushes.White, BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1, 1, 1, 1) };
bord.Child = new TextBlock() { Text = "some content..." };
pop.Child = bord;
The popup is opening and rendering, but it is empty, so it can't be seen.
the problem is here
Border bord = new Border() { Background = Brushes.White, BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1,1,1,1) };
pop.DataContext = bord;
Datacontext is used to set Binding targets, which an empty popup has no bindings.
You need the fill the child object instead by changing the above into
Border bord = new Border() { Background = Brushes.White, BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1,1,1,1) };
pop.Child = bord;
this sets the root of the popup container to ther Border object.
You will also have to do the same with the stack panel and border
StackPanel stack = new StackPanel() { Margin = new Thickness(5, 5, 5, 15) };
bord.Child = stack;

Custom button not rendering correctly

I've got a custom class for a button with a circular image as I'll be using it multiple times through my program. I thought it'd be pretty simple of creating class, inheriting from Button and slapping my setup into a constructor, but when I'm running the program the buttons are massive and plain (no image or text). Here's my class:
public class ImageButton : Button
{
public Button Button;
public ImageButton(string filename) : this(HorizontalAlignment.Center, VerticalAlignment.Center, filename)
{ }
public ImageButton(HorizontalAlignment hAlignment, VerticalAlignment vAlignment, string filename)
{
Button = new Button
{
Width = 35,
Height = 35,
Background = Brushes.Transparent,
HorizontalAlignment = hAlignment,
BorderBrush = Brushes.Transparent,
VerticalAlignment = vAlignment,
Content = new Image
{
Source = new BitmapImage(new Uri("pack://application:,,,/Resources/" + filename))
}
};
}
}
And here's my implementation of one of the instances
private void SetupHeaders(Grid resultGrid)
{
RowDefinition backbtn = new RowDefinition();
backbtn.Height = new GridLength(0.2, GridUnitType.Star);
resultGrid.RowDefinitions.Add(backbtn);
btn_Return = new ImageButton(HorizontalAlignment.Left, VerticalAlignment.Top, "returnicon.png");
Grid.SetRow(btn_Return, 0);
Grid.SetColumn(btn_Return, 0);
resultGrid.Children.Add(btn_Return);
}
with btn_Return being defined at the top of the class as simply
ImageButton btn_Return;
Here's an image of one of the buttons.
In you constructor you inititalize a Button with you properties and then assign it to a property. You never actually use the initialized button. You are always using ImageButton which is nothing more than an inherited button therefore you get the default behavior.
You have to change your constructor.
public ImageButton(HorizontalAlignment hAlignment, VerticalAlignment vAlignment, string filename)
{
Width = 35;
Height = 35;
Background = Brushes.Transparent;
HorizontalAlignment = hAlignment;
BorderBrush = Brushes.Transparent;
VerticalAlignment = vAlignment;
Content = new Image
{
Source = new BitmapImage(new Uri("pack://application:,,,/Resources/" + filename))
};
}

Add a colored Ellipse to MenuItem

I would like to add an Ellipse to some MenuItems of my ContextMenu.
Sadly I could not get this to work [Nothing is displayed].
Canvas canvas = new Canvas() { Height = 16, Width = 16 };
canvas.Children.Add(new System.Windows.Shapes.Ellipse()
{
Height = 16,
Width = 16,
Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Red)
});
System.Windows.Media.Imaging.RenderTargetBitmap bmp = new System.Windows.Media.Imaging.RenderTargetBitmap((int)canvas.Width, (int)canvas.Height, 96, 96, System.Windows.Media.PixelFormats.Default);
bmp.Render(canvas);
MenuItem tmp = new MenuItem();
tmp.Header = "Away";
tmp.Icon = new System.Windows.Controls.Image()
{
Source = bmp
};
AddContextMenuEntry(tmp);
What am I missing or what is wrong here ?
Expected result would be sth. like this:
No image required: Icon is object. It can be any content: Any visual element, any value, any instance of any class. If it's a viewmodel it'll need an implicit DataTemplate. But a red circle is a snap.
MenuItem tmp = new MenuItem();
tmp.Header = "Away";
tmp.Icon = new System.Windows.Shapes.Ellipse()
{
Height = 16,
Width = 16,
Fill = System.Windows.Media.Brushes.Red
};
If you want something more complicated, you could have given it the Canvas instead, with the Ellipse and other child elements.

Put Bold font in title of tab in a tabcontrol c#

I've got this tab control:
I need to put the tab name "Notes" in a bold font but I don't know how to.
I tried this code:
tabControl2.Font = new Font(this.Font, FontStyle.Bold);
However, it put all tabs in bold. Then I tried this:
tabControl2.TabPages["Notes"].Font = new Font(this.Font, FontStyle.Bold);
I also tried this :
How do I make a TabPage's title text bold?
Graphics g = e.Graphics;
Brush _TextBrush;
// Get the item from the collection.
TabPage _TabPage = tabControl2.TabPages["Notes"];
// Get the real bounds for the tab rectangle.
Rectangle _TabBounds = tabControl2.GetTabRect(1);
_TextBrush = new System.Drawing.SolidBrush(e.ForeColor);
// Use our own font. Because we CAN.
Font _TabFont = new Font(e.Font.FontFamily, (float)9, FontStyle.Bold, GraphicsUnit.Pixel);
// Draw string. Center the text.
StringFormat _StringFlags = new StringFormat();
_StringFlags.Alignment = StringAlignment.Center;
_StringFlags.LineAlignment = StringAlignment.Center;
g.DrawString(tabControl2.TabPages["Notes"].Text, _TabFont, _TextBrush, _TabBounds, new StringFormat(_StringFlags));
However, it put all the content of the tab in bold and not the title. I don't know how to put the title of this specific tabpage. Does anyone have an idea ?
I hope I can be of any help to you. 
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
tabControl.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl.DrawItem += TabControlOnDrawItem;
}
private FontStyle HasNotification(string tabText)
{
return tabText.Equals("Notes") && true
? FontStyle.Bold
: FontStyle.Regular;
}
private void TabControlOnDrawItem(object sender, DrawItemEventArgs e)
{
var tab = (TabControl) sender;
var tabText = tab.TabPages[e.Index].Text;
e.Graphics
.DrawString(tabText
, new Font(tab.Font.FontFamily
, tab.Font.Size
, HasNotification(tabText))
, Brushes.Black
, e.Bounds
, new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
});
}
}

How To Add A Border To DataGrid Column Cells

I am displaying data in a WPF DataGrid and the first column shows the static text "View". I added the code below to make the text look like a button. I don't want to do a lot of work to create a button column custom template. This is almost working; the text is centered, the border is drawn. The only thing not working is the background does not appear - I can still see the underlying alternating row colors. Is there something else I need to do to activate the background color, or does the problem arise because the TextBlock is nested inside the DataGridCell and (I think) some other objects?
[I've also tried creating the Background setter with TextBlock.BackgroundProperty and that doesn't work either. And I tried setting BackgroundProperty to an ImageBrush which would be even better, but it couldn't find my image location.]
private void dgvDetail_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
string sHeader = e.Column.Header.ToString();
if (sHeader.Trim().ToLower() == "view")
{
e.Column.CellStyle = GetViewColumnStyle();
}
}
private Style GetViewColumnStyle()
{
Style oStyle = new Style(typeof(DataGridCell));
Setter oTextAlignment = new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center);
oStyle.Setters.Add(oTextAlignment);
Setter oBackground = new Setter(DataGridCell.BackgroundProperty, Brushes.LightGray);
oStyle.Setters.Add(oBackground);
Setter oForeground = new Setter(DataGridCell.ForegroundProperty, Brushes.Black);
oStyle.Setters.Add(oForeground);
Setter oBorderBrush = new Setter(DataGridCell.BorderBrushProperty, Brushes.Black);
oStyle.Setters.Add(oBorderBrush);
Setter oMargin = new Setter(DataGridCell.MarginProperty, new Thickness(2, 2, 2, 2));
oStyle.Setters.Add(oMargin);
return oStyle;
}
You are only styling the TextBlock inside. You should set DataGridCell.Template:
private Style GetViewColumnStyle()
{
// The TextBlock
FrameworkElementFactory textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
// DataBinding for TextBlock.Text
Binding textBinding = new Binding("YourTextBindingPath");
textBlockFactory.SetValue(TextBlock.TextProperty, textBinding);
//Other TextBlock attributes
textBlockFactory.SetValue(TextBlock.TextAlignmentProperty, TextAlignment.Center);
textBlockFactory.SetValue(TextBlock.BackgroundProperty, Brushes.LightGray);
textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Black);
textBlockFactory.SetValue(TextBlock.MarginProperty, new Thickness(2, 2, 2, 2));
// The Border around your TextBlock
FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border));
borderFactory.SetValue(Border.BorderBrushProperty, Brushes.Black);
borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1, 1, 1, 1));
// Add The TextBlock to the Border as a child element
borderFactory.AppendChild(textBlockFactory);
// The Template for each DataGridCell = your Border that contains your TextBlock
ControlTemplate cellTemplate = new ControlTemplate();
cellTemplate.VisualTree = borderFactory;
// Setting Style.Template
Style oStyle = new Style(typeof(DataGridCell));
Setter templateSetter = new Setter(DataGridCell.TemplateProperty, cellTemplate);
oStyle.Setters.Add(templateSetter);
return oStyle;
}

Categories

Resources