How to add borders to WPF ListView in code - wpf

I have created a ListView with a GridView in code.
ListView gridList = new ListView();
GridView gridListView = new GridView ();
gridList.View = gridListView;
Now, I define a GridViewColumn, set the header, width and bindingPath. All good and the data shows up.
GridViewColumn listColumn = new GridViewColumn();
listColumn.Header = "Some Header";
listColumn.Width = 100.0;
listColumn.DisplayMemeberBinding = new Binding("Name");
gridListView.Columns.Add(listColumn);
But there are no borders/gridlines shown on display of this ListView. How can I add borders through code?
Someone described my exact problem here but no good solution mentioned
http://social.msdn.microsoft.com/Forums/en-US/fa4fa8e0-81fe-487a-8763-590062d29c06/wpf-listview-gridview-row-border?forum=wpf

The logic in WPF programming is totally different from what you've done in winforms. Everything related to UI should always be set up using XAML (as much as possible). The WPF library itself has many parts desgined mainly for use in XAML although there is always an equivalent codebehind. However that's when using codebehind may be awkward and non-intuitive (as well as straight-forward).
I understand that you want something like the ListView Grid in Winforms. In WPF that can be achieved easily if you use XAML code. Even in code behind, you can always build a Style or Template from XAML string (with the help of XamlReader). This approach is good for complex scenario but in this case I have another approach (don't use the XAML parser at all). This trick does render the grid which is good enough (and at best it can do for the trade-off of simplicity):
//we need an instance of Style to set to ListView.ItemContainerStyle
var style = new Style(typeof(ListViewItem));
//set the bottom border thickness to 1
var setter = new Setter(Control.BorderThickness, new Thickness(0,0,0,1));
style.Setters.Add(setter);
//set the border brush
var borderBrush = new LinearGradientBrush { StartPoint = new Point(0,0),
EndPoint = new Point(1,0)};
var gradStop = new GradientStop(Colors.Transparent, 0.001);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Green, 0.001);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Green, 0.999);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Transparent, 0.999);
borderBrush.GradientStops.Add(gradStop);
setter = new Setter(Control.BorderBrush, borderBrush);
style.Setters.Add(setter);
yourListView.ItemContainerStyle = style;
Note that the default inner Border of each ListViewItem has a hard-coded CornerRadius of about 2, so by setting just the bottom BorderBrush to a solid brush such as Brushes.Green will show a little upwards curly line at the 2 ends of the bottom border. You can try it yourself. If this result is acceptable, the code can be shorter and simpler (because you don't have to define the GradientBrush to cut-off the 2 curly ends) like this:
setter = new Setter(Control.BorderBrush, Brushes.Green);
style.Setters.Add(setter);
If the behavior is still not what you want. You should try the approach I mentioned about using XamlReader to parse a XAML string and get an instance of whatever you want in codebehind. (you can search it yourself, it's easy to have some result).

I suggest you see this link, it contains a dynamic GridView created in code-behind that can be useful for your specific case. For the code sample that you provided, you didn't add ShowGridLines property.

Related

Why does my ColumnHeadersDefaultCellStyle keep being reset in Visual Studio designer?

I am trying to make the column headers of my DataGridView bold, in Visual Studio 2008.
Every time I change my ColumnHeadersDefaultCellStyle to Calibri 9.75pt bold, using the properties box, the next time I reopen the saved form, the ColumnHeadersDefaultCellStyle has reverted to Calibri 9.75 without bold.
My form's font is Calibri 9.75 without bold, as is my default cell style, but I should be able to override the default cell style with my ColumnHeader style right?
I can solve this problem programmatically by setting the style when the form is shown, but we would like to have the Visual Studio designer show the bolded headers, so we can layout the columns appropriately for the space taken up by bold header text.
In addition, the actual designer file specifies that the ColumnHeadersDefaultCellStyle is bold, even though the designer interface says it is not bold.
dataGridViewCellStyle1.Font = new System.Drawing.Font("Calibri", 9.75F,
System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.receiptDetailView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
Have you tried check EnableHeadersVisualStyles value?
According to MSDN:
If visual styles are enabled and EnableHeadersVisualStyles is set to
true, all header cells except the TopLeftHeaderCell are painted using
the current theme and the ColumnHeadersDefaultCellStyle values are
ignored.
It is a bug, although Microsoft would probably try to call it a feature. The DataGridView header cells are supposed to inherit the current theme only if EnableHeadersVisualStyles is set to TRUE, and use the settings in ColumnHeaderDefaultCellStyles if it is false. But the DGV ignores EnableHeadersVisualStyles and always inherits the font of the parent container it resides in.
Both rutlean's and Nico Engler suggestions will work. Here is what I always do as a standard practice: Put your DGV in a panel (depending on your application, you might want to set the Dock property to fill. Then set the Panel's font to your desired settings. Your DGV will now always inherit that setting.
I found a workaround where just editing the XXXX.Designer.cs with following code does the trick.
this.receiptDetailView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.receiptDetailView.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Bold);
It seems that this is a bug, though I am not sure why it happens. I have tested it in every possible way and the value is overriden by the parent control value regardless of whether it is set or not. This is the opposite of how every other WinForms (or any other UI framework) control works, and doesn't make any sense. I have also tested various other controls and have not found another case where this happens.
The ColumnHeadersDefaultCellStyle Font only matters if the Font property is not set on the parent control (form in this case).
I am giving the bounty to the most upvoted answer but that is not what's going on here.
The "solution" to this that I've been using is to set the font again in the form load event, however this is not a perfect solution since such code doesn't belong there.
I ran into this same issue. However, my dataGridView is located in a groupbox. On a restart of VS 2010, the dataGridView fonts will always be whatever the groupBox is set to. Definitely a bug I would like.
I resolved this problem by adding a frame. For me, the datagridview was inside a groupbox (although a few other container types did the same).
Resolved by putting a panel inside the groupbox, set the appropriate font to that panel, put the datagridview inside that panel and by default it inherits the fonts.
I am using VS2010
The answer is actually pretty simple.
You set a Font Style to Form1 [Arial; 8,25pt].
Lets see the designer :
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle1.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1,
this.Column2,
this.Column3});
this.dataGridView1.EnableHeadersVisualStyles = false;
this.dataGridView1.Location = new System.Drawing.Point(49, 62);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(443, 309);
this.dataGridView1.TabIndex = 0;
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.Name = "Column1";
//
// Column2
//
this.Column2.HeaderText = "Column2";
this.Column2.Name = "Column2";
//
// Column3
//
this.Column3.HeaderText = "Column3";
this.Column3.Name = "Column3";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 14F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(546, 457);
this.Controls.Add(this.dataGridView1);
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
Now as you can see, your font setting for Datagridview header did saved.
But still, font setting for your form appeared after that, which eventually overrides Datagridview font setting.
My advice is return the Form font setting to default.
Use this code
dataGridView1.EnableHeadersVisualStyles = false;
dataGridView1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
Try this:
DataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("Calibri", 9.75F, FontStyle.Bold);
This is a bug and still there even in .net 4.6, the problem is that the ColumnHeadersDefaultCellStyle font always overwritten by its Parent font so I figured out a fix for this:
First you need to add your DataGridView to an own Panel, the Panel will work here as a shield and I believe you need to set the Dock property of the DataGridView to Fill.
Second you need to add the following code into ColumnHeadersDefaultCellStyleChanged event.
If Parent IsNot Nothing Then
Parent.Font = ColumnHeadersDefaultCellStyle.Font
End If
I had the same issue today and it seemed that the ColumnHeadersDefaultCellStyle of the DataGridView is overwritten by the font style of the form it belongs to.
As a solution I set the GdiCharSet parameter of the form's font to 0. After that beeing done, the font of the ColumnHeadersDefaultCellStyle won't be overwritten.
I'm on VS 2010 and Window 8.
I know this topic is old, however I was having the same issue in VS 2015 with the ColumnDefaultHeadersCellStyle font size always reverting to 10pt (I needed it to be 14pt). I was able to fix this by first changing the font itself, which then allowed me to change the font size.
The font I was originally using was SEGOE UI SEMIBOLD, which I changed to just SEGOE UI and was able to change the size. I haven't looked into why using the semibold version prevented me from changing the size. Further, this method has worked for me with VisualStyles enabled, and EnableHeadersVisualStyles set to true.
If anyone is still having this problem, my suggestion would be try changing to another font.
You can try that;
Private Sub DgvListeFt_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DgvListeFt.CellPainting
Call KolonBaslikDGV(sender, e)
End Sub
Sub KolonBaslikDGV(ByVal S As Object, ByVal E As DataGridViewCellPaintingEventArgs)
E.PaintBackground(E.CellBounds, True)
If E.RowIndex = -1 Then
If E.Value Is Nothing Then
E.Handled = True
Return
End If
E.Handled = True
Dim headerFont = New Font("Ariel", 9, FontStyle.Regular)
Dim myBounds As Rectangle = E.CellBounds
myBounds.X = E.CellBounds.X + 4
Dim sf = New StringFormat With {.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center}
E.Graphics.DrawString(E.Value.ToString, headerFont, Brushes.MediumVioletRed, myBounds, sf)
headerFont.Dispose()
sf.Dispose()
End If
End Sub

WPF Data Binding of Width Property

I'm trying to bind the Width property of a Canvas to the Width property of a Shape instance. So the Shape Width should be updated when the Canvas Width gets a new value
I want to do that in code, without XAML, because I create these elements on runtime.
I tried this, but it didnt work (the code is inside of my Canvas):
Binding binding = new Binding();
binding.Mode = BindingMode.OneTime;
binding.Source = this;
binding.Path = new PropertyPath("Width");
shape.SetBinding(FrameworkElement.WidthProperty, binding);
Thanks a lot for your help!
ksman
OneTime looks wrong. I think you want to use OneWay or TwoWay. Check the BindingModes
Edit
Since OneWay and ActualWidth didn't fix your problem, I should recommend you use a tool for debugging bindings. I use Snoop because it is free, but there are others. Debugging WPF without a tool like this can be painful.
You probably want to bind to ActualWidth and not Width.
Width is an input into the layout process -- it's something you may (but don't have to) specify.
ActualWidth is an output of the layout process -- it's the actual width that you see on the screen. This is partly determined by Width, if present, but other factors go into it too (especially if you didn't explicitly set Width in your XAML).

Silverlight Windows Phone 7: How to add content to a PivotControl?

I have a pivot control:
PivotItem sectionPivot = new PivotItem()
{
Header = sect.Name,
Content = new StackPanel()
};
How can I add content to it?
Edit: The reason I'm doing it programmatically is because I don't know how many pivots there will be or what they will contain until runtime. Is there some way to do that in XAML?
If you're going to do it all programatically, just add stuff to the stack panel you just created.
var panel = new StackPanel();
panel.Children.Add(new TextBlock() { Text = "Hello" });
PivotItem sectionPivot = new PivotItem()
{
Header = sect.Name,
Content = panel;
};
I typed all that without doing any checking, but hypothetically that should work...
Another answer from me. The OP added info to the question that they don't know how many there could be, and if you could still do it in XAML.
Yes, you can.
The Pivot control has an ItemsSource property, and you could bind that to something in your class that is being populated dynamically.
<controls:Pivot Title="MY APPLICATION" ItemsSource="{Binding MyPivotItemsSource}" />
Each item in that source would end up as a pivotitem. You'd also have to set up templates and stuff, so its still a lot of work...

WPF Binding with a Border

I have a group of borders that make up a small map. Ideally I'd like to be able to bind the border's background property to a property in a custom list and when that property changes it changes the background.
The tricky thing is, I have to do this in code behind.
Use the FrameworkElement.SetBinding method:
myBorder.SetBinding(Border.BackgroundProperty, "CurrentBackground");
or, if you need sources and converters and things:
myBorder.SetBinding(Border.BackgroundProperty,
new Binding(somePath) {
Source = something,
Converter = new WonderConverter()
// etc.
});

How to override application styles in a wpf control created at runtime

I am trying to create a WPF control at runtime, but I can't figure out how to make it ignore the styles coming from the App.xml resources. I've tried setting the style to null and the OverridesDefaultStyle to true but no luck. The app settings set the foreground to white, and I can't seem to explicity set it to anything else.
Label tb = new Label();
tb.OverridesDefaultStyle = true;
tb.Style = null;
tb.Foreground = new SolidColorBrush(Colors.Black);
this.Children.Add(tb);
Edit: For some reason I never could get the Label to work but when I switched to the textbox, it worked fine.
Thank you for your responses.
All you have to do is set Style to null to stop it from inheriting. Then you can set the Foreground to whatever you like:
var tb = new TextBlock() { Text = "Hello" };
tb.Style = null;
tb.Foreground = Brushes.Blue;
this.Children.Add(tb);
If this isn't working for you, I'd suggest something else entirely is going on.
PS. Use Brushes.Black rather than creating your own SolidColorBrush. Not only is it cleaner, the brush will also be frozen. Your code creates an unfrozen brush, which is less efficient. You can also freeze it yourself by calling Freeze() on the brush.
The following near-identical code works for me:
Label l = new Label();
l.Content = "Fie!!!";
l.Style = null;
l.OverridesDefaultStyle = true; // not required, see below
l.Foreground = new SolidColorBrush(Colors.Blue);
((Grid)Content).Children.Add(l);
From experimenting, however, it seems that if you set OverridesDefaultStyle = true after setting Style, it works okay. But if you set OverridesDefaultStyle before setting Style, it all goes wrong. (No, I don't know why this happens! grin) So move the OverridesDefaultStyle setter to after the Style setter, or (since it's not required for the effect you want), just remove it.

Resources