How to set just only a side of WPF control margin? - c#

I'm trying set a margin of a Image Control top margin, I can get this value with Margin.Top, but why can I set this with image1.Margin.Top = 5;?
How to can I set just this only value?

This is because the property accessor does not give you a reference to the object. It is simply a wrapper around a DependencyProperty, which returns the value via GetValue. If you want to change that item, you must do this:
Thickness margin = image1.Margin;
margin.Top = 5;
image1.Margin = margin;

Related

WPF Binding Without XAML

I have a WPF app with a "Grid Window". This window has no added XAML to it. I create a grid (columns and rows) then place a rectangle in each one all in C#.
This allows me to make a grid where I set the 'Stroke' and show locations on the grid when I set the 'Fill'.
The entire grid is set the same, in other words, if one part of the grid is red, the whole grid is red. Currently I set the grid by iterating through all of the rectangles and setting the 'Stroke' property. That works fine but seems very slow compared to most of the other operations. I would like to bind the stroke property to a variable in the C# (unless iterating is a reasonable way to handle it).
I have looked at quite a few questions here, but most want to use XAML. My code below is based off of Binding without XAML [WPF]. No errors, the grid just never shows up.
// put a rectangle in each square
for (int i = 0; i < x; i++) // for each column
{
for (int j = 0; j < y; j++) // for each row
{
// create a new rectangle with name, height, width, and starting color (transparent)
var rect = new Rectangle()
{
Name = $"rec{(i + 1).ToString("00")}{(j + 1).ToString("00")}", //column 5 row 2 -> rec0502
Height = squareSize,
Width = squareSize,
Fill = _ColorOff
};
// create the binding
var binder = new Binding
{
Source = _GridColor, // Brush that is updated on color change
Path = new PropertyPath("Stroke")
};
// apply the binding to the rectangle
rect.SetBinding(Rectangle.StrokeProperty, binder);
rect.DataContext = binder;
// place the rectangle
Grid.SetColumn(rect, i); // current column
Grid.SetRow(rect, (y - j - 1)); // same row but from the bottom (puts point 0,0 at bottom left)
// add the rectangle to the grid
grdBattleGrid.Children.Add(rect);
}
}
Even if iterating is fine, I'd still like to know what I'm doing wrong.
EDIT: The color name is chosen from a ComboBox on a separate window. This updates the user settings, which in turn throws an event my "Grid Window" is subscribed to. I convert the name to a SolidColorBrush before iterating though the rectangles.
The most simple solution would be not to have any Binding at all. Assign _GridColor to the Rectangle's Stroke. Whenever the Color property of (the assumed SolidColorBrush) _GridColor changes, it affects all Rectangles.
public SolidColorBrush _GridColor { get; } = new SolidColorBrush();
...
var rect = new Rectangle
{
Name = $"rec{(i + 1).ToString("00")}{(j + 1).ToString("00")}",
Height = squareSize,
Width = squareSize,
Fill = _ColorOff,
Stroke = _GridColor // here
};
Grid.SetColumn(rect, i);
Grid.SetRow(rect, (y - j - 1));
grdBattleGrid.Children.Add(rect);
Change the Rectangle Stroke by assigning a value to the Color property of the _GridColor Brush:
_GridColor.Color = Colors.Red;
You just need to set the DataContext one time for the Window, not for each Rectangle.
Is Binding your own view model class from INotifyPropertyChanged interface? Link to MS Docs

Can't set TextBox.MinWidthProperty when creating a VisualTree for GridViewColumn.DataTemplate

I have am trying to set a GridViewColumn.DataTemplate to a TextBox VisualTree. The code so far is:
//GridViewColumnCollection columns
DataTemplate template = new DataTemplate();
FrameworkElementFactory elementFactory = new FrameworkElementFactory(typeof(TextBox));
elementFactory.SetBinding(TextBox.TextProperty, new Binding { Path = new PropertyPath("Position") });
elementFactory.SetValue(TextBox.MinWidthProperty, new GridLength(50));
template.VisualTree = elementFactory;
columns[1].CellTemplate = template;
When I run this code I get the following error:
50 is not a valid value for property 'MinWidth'.
on this line:
elementFactory.SetValue(TextBox.MinWidthProperty, new GridLength(50));
I also tried setting the value to just 50, but to no avail!
What am I doing wrong?
Thanks in advance.
According to MSDN, the MinWidth dependency property is of type double. You should set it to a double instead of a GridLength object.
Property Value
Type: System.Double
The minimum width of the element, in device-independent units (1/96th inch per unit). The default value is 0.0. This value can be any value equal to or greater than 0.0. However, PositiveInfinity is not valid, nor is Double.NaN.
I totally assent with bouvierr. I was working on a WPF project and this was something I also run into. Eventually, through the MSDN documentation, I noticed that the code behind concept only accepts double data type as supposed to an integer.
textBox.SetValue(HeightProperty, 120.0);
textBox.SetValue(WidthProperty, 360.0);
textBox.SetValue(FontSizeProperty, 14.0);
textBox.SetValue(MinWidthProperty, 50.0);

DockLeft custom size

I am trying to set DocContent DockLeft to custom size but it is not working. Can anyone suggest how to accomplish this?
I was testing this code but it ends up with default width 404 not 700 as I set.
dockPanelMain.SuspendLayout(true);
DockContent myContent = new MenuForm();
myContent.ShowHint = WeifenLuo.WinFormsUI.Docking.DockState.DockLeft;
myContent.Show(dockPanelMain);
dockPanelMain.DockWindows[WeifenLuo.WinFormsUI.Docking.DockState.DockLeft].Width = 700;
dockPanelMain.ResumeLayout(true, true);
DockLeftPortion
Size of the left docking window. Value < 1 to specify the size in portion;
value > 1 to specify the size in pixels.

HowTo define the "Auto" Width of the WPF GridView Column in Code?

I want to define the "Auto" width of a GridView Column in the code. How can I do that?
var grid = (GridView)myListview.View;
grid.Columns.Add(new GridViewColumn
{
Header = "My Header",
DisplayMemberBinding = new Binding("MyBinding"),
Width = ??? // Auto
});
GridViewColumn's Width property is of type double, but according to the MSDN page you can set it to Double.NaN ("not a number") to tell it to auto-size.
If you do that, you have to ask for its ActualWidth if you want to know the width it has auto-sized to.
In case you're looking to do the same thing in code for the Width property of a Column of a normal Grid control, use GridLength.Auto.

Setting Margin Properties in code

MyControl.Margin.Left = 10;
Error:
Cannot modify the return value of 'System.Windows.FrameworkElement.Margin' because it is not a variable
The problem is that Margin is a property, and its type (Thickness) is a value type. That means when you access the property you're getting a copy of the value back.
Even though you can change the value of the Thickness.Left property for a particular value (grr... mutable value types shouldn't exist), it wouldn't change the margin.
Instead, you'll need to set the Margin property to a new value. For instance (coincidentally the same code as Marc wrote):
Thickness margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;
As a note for library design, I would have vastly preferred it if Thickness were immutable, but with methods that returned a new value which was a copy of the original, but with one part replaced. Then you could write:
MyControl.Margin = MyControl.Margin.WithLeft(10);
No worrying about odd behaviour of mutable value types, nice and readable, all one expression...
The Margin property returns a Thickness structure, of which Left is a property. What the statement does is copying the structure value from the Margin property and setting the Left property value on the copy. You get an error because the value that you set will not be stored back into the Margin property.
(Earlier versions of C# would just let you do it without complaining, causing a lot of questions in newsgroups and forums on why a statement like that had no effect at all...)
To set the property you would need to get the Thickness structure from the Margin property, set the value and store it back:
Thickness m = MyControl.Margin;
m.Left = 10;
MyControl.Margin = m;
If you are going to set all the margins, just create a Thickness structure and set them all at once:
MyControl.Margin = new Thickness(10, 10, 10, 10);
Margin is returning a struct, which means that you are editing a copy. You will need something like:
var margin = MyControl.Margin;
margin.Left = 10;
MyControl.Margin = margin;
One could simply use this
MyControl.Margin = new System.Windows.Thickness(10, 0, 5, 0);
One would guess that (and my WPF is a little rusty right now) that Margin takes an object and cannot be directly changed.
e.g
MyControl.Margin = new Margin(10,0,0,0);
To use Thickness you need to create/change your project .NET framework platform version to 4.5. becaus this method available only in version 4.5. (Also you can just download PresentationFramework.dll and give referense to this dll, without create/change your .NET framework version to 4.5.)
But if you want to do this simple, You can use this code:
MyControl.Margin = new Padding(int left, int top, int right, int bottom);
also
MyControl.Margin = new Padding(int all);
This is simple and no needs any changes to your project
Depends on the situation, you can also try using padding property here...
MyControl.Margin=new Padding(0,0,0,0);
Margin = new Thickness(0, 0, 0, 0);
It's a bit unclear what are you asking, but to make things comfortable, you can inherit your own Control and add a property with the code that Marc suggests:
class MyImage : Image {
private Thickness thickness;
public double MarginLeft {
get { return Margin.Left; }
set { thickness = Margin; thickness.Left = value; Margin = thickness; }
}
}
Then in the client code you can write just
MyImage img = new MyImage();
img.MarginLeft = 10;
MessageBox.Show(img.Margin.Left.ToString()); // or img.MarginLeft

Categories