I'm trying to get the following to work. I need a trackbar in a grid cell, but with labels on both sides to display the min and max value of the trackbar. I have managed to get the trackbar in the grid's cell, but I don't seem to get the labels in place.
First I tried to a CreationFilter to add TextUIElements. This worked, but I couldn't 'shrink' the TrackBar itself, so the labels were drawn over the TrackBar.
I also looked at the DrawFilter, but could not really find a good solution there.
Finally I tried to use a custom user control using a ControlContainerEditor. But because I need to have the user control displayed both in rendering and edit mode, I had to create two instances of my user control, because for some reason I can't use the same instance for rendering and editing. But this gave problems with 'syncing' the actual value between the two user controls. And when clicking the dragger on the trackbar, it didn't become draggable immediatly. It first putted the cell in edit mode, and then I could drag the control. I might be able to fix the syncing issues, but it just doesn't feel like the right way to solve this.
I hope someone can provide me a solution using a CreationFilter (or DrawFilter). I think I came pretty close to the answer, I just need to shrink the trackbar to allow space for the labels. Below is the code I have so far.Thanks in advance.
public class TrackbarLabelCreationFilter : IUIElementCreationFilter { public bool BeforeCreateChildElements(UIElement parent) { return false; } public void AfterCreateChildElements(UIElement parent) { if (parent is TickmarkAreaUIElement) CreateLabels(parent); } private static void CreateLabels(UIElement parent) { ClearLabels(parent); var column = (UltraGridColumn)parent.GetContext(typeof(UltraGridColumn)); AddLabel(parent, column.MinValue.ToString(), HorizontalAlignment.Left); AddLabel(parent, column.MaxValue.ToString(), HorizontalAlignment.Right); } private static void ClearLabels(UIElement parent) { for (var i = parent.ChildElements.Count-1; i >=0; i--) { var element = parent.ChildElements[i]; if (element is TextUIElement) parent.ChildElements.Remove(element); } } private static void AddLabel(UIElement parent, string value, HorizontalAlignment alignment) { var label = new TextUIElement(parent, value) { Rect = GetLabelRectangle(parent, alignment) }; parent.ChildElements.Add(label); } private static Rectangle GetLabelRectangle(UIElement parent, HorizontalAlignment alignment) { int x, y, w, h; w = 20; h = parent.RectInsideBorders.Height - 2; x = alignment == HorizontalAlignment.Right ? parent.RectInsideBorders.Right - 2 - w : parent.RectInsideBorders.Left + 2; y = parent.RectInsideBorders.Y + 2; return new Rectangle(x, y, w, h); } }
Hi,
The CreationFilter approach is probably not the way to go. You could easily shrink the embeddable TrackBar element itself, but this will not affect it's child elements. So you would have to handle this shrinking all the way down into the element tree. And even then, I am not sure it will work, because the control itself might be making assumptions about finding the correct value from a particular point that resizing the elements won't handle correctly.
I think your best bet here is the ControlContainerEditor approach.
You don't have to do any synching between the two controls. The reason you need two instances of the control is because the user has to be able to interact with the cell that is currently in edit mode in the grid and at the same time, the grid has to be able to paint the other cells in the column. So the EditingControl is used for editing the current cell and the RenderingControl is used to draw the other cells. There is no synching required.
The only thing you do need to do is make sure your UserControl has a single property that links up to the Value of the Value of the TrackBar and works both ways - setting the Value on the UserControl sets the value of the Trackbar and the property returns the Value of the Trackbar. You also need to send an IPropertyChanged notification whenever the value changes, but this is easy enough.
The mouse behavior might be a problem, but I think you might be able to get around it by setting EnterEditModeMouseBehavior on the UltraControlContainerEditor to EnterEditModeAndMouseDown. This will forward the MouseDown message which enters edit mode on the grid on to the EditingControl.