WPF scrollviewer - wpf

Is there a posibility to scroll to a specific place in a ScrollViewer from your code behind?
So something like the Slider element you can change the value property...

You need the ScrollToHorizontalOffset and ScrollToVerticalOffset methods.
Annoyingly, there aren't corresponding (settable) properties, so you can't databind the scroll position, but these methods do at least let you set it from code.

In most cases if you're trying to show a specific control it's simpler to call BringIntoView on any FrameworkElement (Panel, Control, etc) contained in the ScrollViewer which will take care of all the size and offset calculations for you.

Related

Bind +/- images to slider?

Hi I have an image of a '-' to the left of my slider, and an image of a '+' to the right.
How do I bind these images such that if they are clicked on they will increase or decrease the slider by my value of SMALLCHANGE?
Thanks.
Mind that the easiest way is to just name your Slider, handle the Image.MouseLeftButtonUp in the UserControl and change its value in code behind. If you doesn't plan to reuse this behavior, there is no need to do any further.
To make this behavior reusable, there are several approaches. Initially I'd suggest using a EventTrigger in the image with a CallMethodAction bound to the Slider, but the Slider does not has methods like LargeIncrement, SmallIncrement, LargeDecrement, SmallDecremenet. You could subclass it and implement these methods yourself, though.
Another option is to create an AttachedProperty like "IncrementSlider" to the Image (or any FrameworkElement), which would receive a Slider instance through a ElementName binding. In the PropertyChangedCallback (see this) of the PropertyMetadata, you could subscribe to the MouseLeftButtonUp event of the control and modify the Slider. You could create other attached properties as well, like "DecrementSlider", "SmallIncrementSlider", as well.
A better solution than the AttachedProperty in this case would be an AttachedBehavior. You can create a behavior to a FrameworkElement (or just Image) with a Slider property and other control properties, like "IncrementOrDecrement" and "SmallOrLarge". In the behavior's OnAttached method you would subscribe to the MouseLeftButtonUp of the control to update the Slider (if there is one available). You could then attach the behavior to the Images, bind the Slider property of the behavior to the desired Slider, and configure it to each of them, to increment or decrement in large or small steps.

WPF Height at Runtime

I am new to WPF. A Problem I am trying to solve is how I can get a correct height at runtime.
In my Application I dynamically add Usercontrols to a Stackpanel in the Code behind. The Usercontrol contains a few Texblocks. My Stackpanel is then used as Content for a BookPage and this BookPage is added to a Book(http://wpfbookcontrol.codeplex.com/). The Height of my Stackpanel should not exceed a certain value.
I already figured out that I can use Measure & Arrange to calculate the ActualSize & Height of the Usercontrol:
itemsa.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
itemsa.Arrange(new Rect(0, 0, 400, itemsa.DesiredSize.Height));
At this point the Usercontrol isn't added to the Stackpanel. 400 is the Width my usercontrol shouldn't exceed, but it does, because the Textblock dosn't create automatic linebreaks. When I display the Book the linebreaks are created.
What should I do to solve this Problem?
Thanks in advance.
Not sure if you're looking for this, but with the MaxHeight property you have the possibility to restrict the growing of a control.
In general, it's not necessary to override Measure and Arrange, the Layout-System is very powerfull and it offers you many container-controls that provide specific layout behaviour.
Why not use the property MaxHeight for the stackpanel?
Also ActualWidth and ActualHeight will tell you the actual size of a control.
Are you sure you need all these calculations? My guess is that it would be better to use auto sizing GridRows or something like that.
It sounds to me like you want a custom panel to do layout in a very specific manner. You can inherit a new class from Panel, and then override MeasureOverride and ArrangeOverride to determine what can be added and where. This is also the method you'd use to do a virtual panel, where only the visible children are created and they are destroyed when scrolled off.
If you are interested in this let me know and I'll edit the post and provide an example.

In a Silverlight CustomControl how can you layout elements of that control according to a Grid that contains the Control?

Assume a custom control in Silverlight that has three TextBlock elements named Left, Middle and Right. I want to place the control inside of a grid that has three columns, and I would like the position of those elements to be the same as if I had defined them inline using Grid.Column="x" syntax, with the Grid.Row attached property being set on the custom control itself.
Or if I am completely off-base, what is the best way to achieve a similar result.
I think its likely that you are way "off-base". The purpose of a custom control is to present data in a unique way. If you want to hand out the the layout to an external grid then I would suggest that you don't have call for a custom control.
It seems more likely that you would want a class that has three properties to which you are simply binding three TextBlocks. Without further particulars its hard to give better advice.
To answer your actual question, you can't. You would need to add individual elements directly to the Children collection of the Grid in order for the grid to take charge of their layout. This means that these elements cannot appear as child visual elements inside your custom control.
My first thought was that you are off-base :) but you must have a good reason for seeking that solution.
In your CustomControl you override OnApplyTemplate. In this method you can find the three TextBlocks and set the Grid.Column value using SetValue.
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
/// Find TextBlock named "Left"
var left = GetTemplateChild("Left") as TextBlock;
left.SetValue(Grid.ColumnProperty, 0);
...
}

how can we change zindex of a silverlight control programmatically?

I have some controls added in a stackpanel programmatically. What i want to do is that i want one of the controls in this stackpanel to be placed over another control. Specifically, I want to place button over an image in this stack panel. I couldn't find zindex property in c# codebehind. Although it seems very simple problem but i am unable to find any clue to solve this problem. Anyone please......??
Try placing all your controls on Canvas. Then you can set Zindex with:
this.controlName.SetValue(Canvas.ZIndexProperty, 10d);
Only the Canvas panel supports a ZIndex property. Stackpanel doesn't because each item is placed one after the other in the panel so they shouldn't overlap each other. This can be a little annoying at times when you have animated transforms moving the items about because the previous assumption isn't actually true.
In general though if you need to place items in a visual stack the Stackpanel isn't the right place for it. Perhaps a Canvas or you could use a Grid where the oridinal position of a element determines its "zorder" in a cell.
From xaml:
<StackPanel Canvas.ZIndex="1">
</StackPanel>

Using RenderTransform to increase the size of a DataTemplate in WPF

I'm using a DataTemplate that animates a RenderTransform to increase its size when the mouse is over it. The problem I'm having is that when the animation is in effect the enlarged list box item appears behind other items. Is there a way to control the ZIndex of the list box item from within my DataTemplate so that it's always on top of other items?
You can set the Templated Element's ZIndex from template using Triggers. Find out the templated parent control by VisualTree parsing like bellow
{RelativeSource FindAncestor,AncestorType=...
The zIndex is only available on elements hosted inside a Canvas. Therefore you may be able to wrap the whole listbox control in a canvas then set Canvas.zIndex to 99 as part of the Trigger you are using to do the transform . However I could not get this to work.
The only other option that did work is to use a LayoutTransform rather than a RenderTransform as this will move the other items out of the way as the transform is calculated before the items are placed. This would mean there would be no need to set any zIndex, however it would depend on your requirements.

Resources