Change StackPanel location on a Canvas programmatically - c#

I have stackpanel in a canvas
The stackpanel has
<Canvas x:Name="MyCanvas">
<Slider Template="{StaticResource simpleSlider}" x:Name="seekBar" Thumb.DragStarted="seekBar_DragStarted" Thumb.DragCompleted="seekBar_DragCompleted" Canvas.Left="347" Canvas.Top="746" Width="900" Height="2" />
<Rectangle Height="5" />
<StackPanel Canvas.Left="200" Canvas.Right = "100">
</StackPanel>
</Canvas>
At runtime I need to change the location of the objects within the StackPanel.
Ie seekBar.Canvas.Left = 50

The "Canvas.Left" is an example of attached dependency property. The syntax for the C# is:
Canvas.SetLeft(myStackPanel, 50);
Where myStackPanel is any custom name you must assign using x.Name in the xaml.

You should use Canvas.SetLeft and Canvas.SetRight methods.

Caveat: I'm assuming that by this:
At runtime i need to change the location of the objects within the StackPanel.
You mean that you need to be able to set the Left position of the StackPanel itself (irrespective of what it contains). If this is not what you mean (for example, you don't have anything called seekBar in your example Xaml, even though you reference it in your code), please clarify.
The Canvas uses Attached Dependency Properties (as do other layout items, such as the Grid) to track layout information about contained items. Because of this, you'll either have to use the GetLeft and SetLeft functions on Canvas, GetValue and SetValue functions on your StackPanel to manipulate these values.
Do this, you'll need to give your StackPanel a name. I'll call it stack.
Given your example, you would do either this:
Canvas.SetLeft(stack, 50);
or this:
stack.SetValue(Canvas.LeftProperty, 50);
Note that the first version (SetLeft) is simply a wrapper around the second version, so use whichever you prefer.

You can get the value of any control by var x = btn.TransformToAncestor(this).Transform(new Point(0, 0));
where btn is the control which you want the margin of.
And then use yourstackpanel.SetValue(StackPanel.MarginProperty,new Thickness());

Related

Most simple FrameworkElement to handle HorizontalAlignment and VerticalAlignment?

This is Silverlight.
Initial goal is to display a random element in a Popup with some VerticalAlignment and HorizontalAlignment. I do not want to use VerticalOffset or HorizontalOffset, because there is more to what I really want to do, including some complex bindings.
First attempt was:
<Popup>
<Button
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" />
</Popup>
Second attempt was:
<Popup
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom">
<Button />
</Popup>
Both were a failure: the Button was always on Top and not Stretch (HorizontalAlignment and VerticalAlignment didn't work).
So I had the idea to encapsulate the element in a simple FrameworkElement:
<Popup>
<Border>
<Button
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" />
</Border>
</Popup>
And it is working.
But I had to use Border in this example, when I could have done it with Grid and many other FrameworkElement (but not with Canvas or Viewbox or Popup). I'd like to know what is the most simple, efficient and processor-friendly transparent FrameworkElement to encapsulate another element with working HorizontalAlignment and VerticalAlignment? Is it:
Border? (like the above example)
UserControl?
ContentControl?
ContentContainer?
some custom and basic MyFrameworkElement? (might need help for most basic implementation)
something else like Grid?
WPF controls come in two flavors: Ones that interact with users (like accept user clicks like a button, or display text like a text block) and containers that control placement and layout of the previous ones.
Container controls are usually designed to lay out their children in a specific manner. For example, Canvases lay out children by X, Y, Width & Height values. Each one has a specific use, so you must read the documentation or tutorials for these container controls and understand how each works in order to select the appropriate one for a task.
In your case, you want the button to fill all available space in the popup (it seems, it isn't that clear). I know that the Grid does this by default. So I would do the following:
<Popup><Grid><Button /></Grid></Popup>

Setting width, height of TextBlock behind code for variablesizedwrapgrid not displaying correctly

I need some help confirming I'm seeing a bug.
I am creating a "TagCloud" in xaml for metro. Nothing complex, it should be simple.
I create TextBlock objects in the code behind and then add them to the children of a VariableSizedWrapGrid
Each TextBlock is a different height and width - and this is determined by the testblock.Measure(size), then setting the width and height via DesiredSize.Width and DesiredSize.Height
testblock.Measure(new Size(10000, 250));
dWidth = Double.Parse(testblock.DesiredSize.Width.ToString());
dHeight = Double.Parse(testblock.DesiredSize.Height.ToString());
The problem is, when the TextBlock objects are added they basically clip, they all lock to one single size (basically the behavior of a WrapGrid). Essentially the VariableSizedWrapGrid is refusing to allow variable heights and widths within its child elements? I have no idea why it clips everything.
<VariableSizedWrapGrid x:Name="vswg" Orientation="Horizontal" Width="Auto" Height="200" Grid.Column="1"/>
IEnumerable<TextBlock> textBlocks =
(from cloudItem in cloudItems
select ConvertToTextBlock(cloudItem, fontWeight));
vswg.Children.Clear();
foreach (TextBlock t in textBlocks)
{
vswg.Children.Add(t);
}
The ConvertToTextBlock() returns a new TextBlock with a different text and FontSize
I cannot get the VariableSizedWrapGrid to actually have a "variable sized" child control. Perhaps I am just using this all wrong?
Try Something like this:
<GroupStyle.Panel> <ItemsPanelTemplate > <VariableSizedWrapGrid x:Name="MyGrid" Orientation="Horizontal" MaximumRowsOrColumns="7"
ItemWidth="{Binding DataContext.ItemTemplateWidth, ElementName=pageRoot}"
ItemHeight="{Binding DataContext.ItemTemplateHeight, ElementName=pageRoot}"
></VariableSizedWrapGrid> </ItemsPanelTemplate> </GroupStyle.Panel>
Also consider reading:
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2012/09/14/windows-8-xaml-and-displaying-multiple-sized-items.aspx
http://www.acnenomor.com/3756161p1/how-to-display-gridview-items-with-variable-width-in-window-8
Try considering using DataTemplate.
VariableSizedWrapGrid provid ItemHeight and ItemWidth properties. Then, you can only choose the Width and Height of an item "in cells". So, you can choose your item to fit 3 cells width and 1 cell height.
You should consider reading: http://blogs.u2u.be/diederik/post/2012/03/07/Databinding-to-the-VariableSizedWrapGrid-in-Windows-8-Metro.aspx
Change this:
DesiredSize.Width.ToString()
To this:
Width.ToString()
The layout system is a complex three pass process, when you allow the "DesiredSize" value to be controlled by saying "DesiredSize in the code" the layout system takes charge. When you specify a width the layout system is overridden.

How do I bind a Border in Silverlight 4 XAML to a variable in my C# ViewModel code?

I know how to bind an attribute of a Silverlight XAML Border, Height for example, to a variable in my C# code. But how can I bind the Border item itself to a variable of type Border in my C# code?
Let's say that in my C# code (ViewModel, not code-behind), I have variable of type Border called myBorder. What I want to do is something like this in my XAML:
<Border Source="{Binding myBorder}"/>
But Source, Content, and so on are not attributes of the Border element that are available to be set, so how can I do this?
Your XAML should be like the following
<Border Background="{Binding Path=Background}" DataContext="{Binding myBorder}" Height="{Binding Path=Height}" Width="{Binding Path=Width}"/>
in your vm
myBorder = new Border();
myBorder.Height = 20;
myBorder.Width = 30;
myBorder.Background = Brushes.Blue;
Remember that myBorder should be declared as a Property not a field
Since you are using a ViewModel, I would gather that you are trying to follow the MVVM pattern. In that case, your ViewModel should hold the data that affects the border choice (a boolean value - like IsSelected - , an enumeration, etc.) and you should use a IValueConverter to achieve this. Your XAML would look like:
<Border BorderBrush="{Binding IsSelected,Converter={StaticResource BlueIfTrueRedIfFalseConverter}}"/>
For implementing your ValueConverter, see the following link: http://timheuer.com/blog/archive/2008/07/30/format-data-in-silverlight-databinding-valueconverter.aspx
This means that you now have separation of concerns. Your ViewModel need not concern itself on how it's going to be rendered, that is the View's job.

Accessing inner controls of UserControl

I am building a custom UserControl which would allow me to place text inside a ProgressBar. The problem is, none of the ProgressBar's DependencyProperties get transferred over. Here is the XAML for my custom UserControl.
<UserControl
x:Class = "MyProgram.MyCustomProgressBar"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<ProgressBar Name="uiProgressBar" />
<Label Name="uiLabel" />
</Grid>
</UserControl>
How can I access and set the Minimum, Maximum, Value, etc. from XAML when I start using this UseControl.
<local:MyCustomProgressBar x:Name="uiLoadTime" ??.uiProgressBar.Maximum="50" />
I am hoping I don't need to redefine a bunch of DependencyProperties in order to get this functionality.
The usual way is to use a DependencyProperty... it's not so bad once you got used to it really.
Use the "propdp" built in snippet in the code-behind of your usercontrol.
Let's take the ProgressBar.Maximum example:
Make an integer dependencyproperty with a default value of 100 (or whatever you like), name it InnerProgressBarMax.
In your UserControl's XAML, you bind it this way:
<ProgressBar Maximum="{Binding InnerProgressBarMax, ElementName=myUsrCtrl}" />
When you use the control in another part of your application, simply enter a value like this:
<local:MyCustomProgressBar x:Name="uiLoadTime" InnerProgressBarMax="50" />
Rinse & repeat for each property you want to expose.
Edit:
If you really need to have 50+ DP exposed, you could bring down the hastle by specifying smart default values for your DPs.
To do that, when you create a DP, set the parameter of new PropertyMetadata(YOUR_DEFAULT_VALUE)
Once that is done, your control may expose many DPs, but you'll only have to set a few manually in the XAML code that uses the control.
The alternative to wrapping everything in DependencyProperties is to let the UserControl's consumer provide the ProgressBar. It could look like this:
<local:MyCustomProgressBar x:Name="uiLoadTime">
<local:MyCustomProgressBar.ProgressBar>
<ProgressBar Maximum="50" />
</local:MyCustomProgressBar.ProgressBar>
</local:MyCustomProgressBar>
Then in MyCustomProgressBar.xaml.cs, you would expose a public property for a ProgressBar. In its setter, modify the properties however you see fit, then add it to the UserControl's root Grid.

How to set control's location properly?

My goal is to create report using Dev Express XtraReport. I'm using XRRichText and XRPictureBox controls.
My problem is that I can't set XRPictureBox control's location properly.
I want to Add XRPictureBox control after XRRichText control as it is shown in picture. Is there any way to do this?
Thanks.
<Canvas> - Lets you position child controls explicitly by specifying the distances
between their left, top, right, and bottom edges and those of the <Canvas>. I think it is exactly what you need. Here example how to use it:
<Canvas>
<Button Content=”TopLeft” Width=”85” Height=”30”
Canvas.Top=”20” Canvas.Left=”20”/>
<Button Content=”TopRight” Width=”85” Height=”30”
Canvas.Top=”20” Canvas.Right=”20”/>
<Button Content=”BottomLeft” Width=”85” Height=”30”
Canvas.Bottom=”20” Canvas.Left=”20”/>
<Button Content=”BottomRight” Width=”85” Height=”30”
Canvas.Bottom=”20” Canvas.Right=”20”/>
</Canvas>

Categories

Resources