Elegant way of exposing ItemContainerGenerator in custom control - c#

What's the elegant way of exposing ItemContainerGenerator from custom control?
I have ItemsSource property on my custom control and I would like to access UIElement corresponding to the bound item outside of it.
I don't have access to the ItemsControl nor ItemsContainerGenerator outside of my control. Should I expose ItemsControl or ItemContainerGenerator as a property, or maybe add a method for retrieving the UIElement?
I need to show the popup near the selected item. Maybe the popup should be a part of the control then I wouldn't have to do this?

If you want to be able to access the entire child ItemsControl, create a public read-only property that returns it.
If you only want to expose the ItemContainerGenerator, create a read-only property that returns it, e.g.:
public ChildItemContainerGenerator => childControl.ItemContainerGenerator;
If it makes no sense to expose the entire ItemContainerGenerator, create a public method that uses the ItemContainerGenerator internally to perform whatever you want to.
Which option to choose all comes down to your requirements actually.

Related

How do you bind 2 controls?

In my app, there is a feature to customize it's own Controls (like Textbox, Labels, Textblocks, Buttons, etc), this feature interface is located inside a TabItem. Lets say i want to modify Button A, which is located in ANOTHER container. On the feature interface, i set it's Foreground property to White, at this moment i don't know whether the Button looks better or not, so i have to go to the container which contains that Button.
What am i trying to do is, i want to create a "preview" Control (which is the same type as the actual target) inside the feature interface. I want any changes on this "preview" control are reflected to the actual target Control. With this, i won't need to navigate to where the target Control located.
When i used the title ("How do you bind 2 controls)" with google, all results actually gives me "how to bind SINGLE property of a control to another control's property". What i want is how do you bind/link 2 Controls literally, i mean, i want to bind ALL properties of Control A to ALL properties of Control B.
Binding them one by one is one (tiring) way. Is there another way to achieve this?
I would prefer code-behind method.
There is no "fast" way to do this, you will have to bind one by one according to your buisness logic.
Also a binding is not cheap regarding performance so binding each and every property of a control even those you dont explicitly need, is a warning sign.

Hidden public property in WPF control

I am writing a custom control in WPF that works in this way: user sets some property which type is some class. Then, the control examines this object and generates some collection, which is to be displayed in UI via data binding.
In order for data binding to work, this collection should be a public property, but for the sake of incapsulation I do not want it to be public.
What is the best practice in such a situation?
You can use the Browsable attribute to hide property from property grid and the EditorBrowsable attribute to hide it from the XAML\CS editor. Or you can override the OnApplyTemplate method and assign your property value to the target element. You can get target element using the GetTemplateChild method.

Best Way to Override ComboBox.Items

I've created an owner-draw user control that inherits from ComboBox.
The control stores specialized items, but the Items collection still accepts and returns items of type Object. Any tips on the best way to override this collection to be type-safe?
About the only way I can think of is to create my own collection class. The class wouldn't be a true collection--it would take an ObjectCollection as an argument to the constructor and simply extend the methods of that to.
The user control would pass the original Items collection to the constructor of the new class. And then override the Items property to return an instance of the new class instead.
This seems somewhat convoluted. Is there a better way?
You could do it a couple of different ways. First off, I'm a little confused about you creating a "user control" that inherits from ComboBox. You can create a custom control that inherits from ComboBox, but you cannot inherit from both UserControl (which is the usual definition of a "user control") and ComboBox.
If you define a true UserControl derivative, this gets a little easier. A UserControl, like I said, can't be a ComboBox, but it can have a ComboBox. So, you can drop and Dock a ComboBox to your UserControl surface, and then re-implement any properties you need to be able to use, such as Items. This will allow you to re-create Items as a collection of your choice, probably a strongly-typed List. The only problem will be knowing exactly what you'll want to re-implement; there's a lot of useful properties of a ComboBox that you won't be able to access in the Designer or in code unless you implement a "pass-through" property that modified the contained ComboBox within your UserControl.
If you inherit directly from ComboBox, it gets a little tricker in some ways, easier in others. You can hide the base class implementation of Items by defining your own and using the new keyword. You can change the visibility, type and other modifiers when you do this. This will prevent code that deals with your control as a CustomComboBox (or whatever you name it) from using the object array on the base class; they have to use your strongly-typed Items array. Your new property can still access the old one (which it will need to in order to make it work). You also get all the other public properties of a ComboBox for free; you only have to reimplement what you want to change. However, referring to your custom ComboBox as any base class will cause the runtime to use the version of Items that is valid for that class; that is, the object array, not your strongly-typed one.

Instantiate ItemsPanelTemplate

I'm trying to create a ItemsControl that has a separator between items, for example a control to create a navigation bread crumb. I want the control to be completely generic.
My original method was to create extend ItemsControl, add a SeparatorTemplate property, and then have the class add separators to the ItemsHost of the ItemsControl. The problem with this approach is that if you add extra items to the container panel, the ItemGenerator gets confused and the items are out of order and don't get removed correctly.
So my second plan was to create a completely new control that would emulate an ItemsControl, but the problem I'm running into is that I can't find a way to instantiate an ItemsPanelTemplate. I would like to provide an ItemsPanel property just like ItemsControl, but I can't then create a panel from that template.
Can anyone think of a way to either instantiate an ItemsPanelTemplate or way to add controls to an ItemsControl's panel without breaking the ItemGenerator?
Well I haven't tried it myself but I would have thought you would override the GetContainerForItemOverride to acheive this.
You could create a new BreadCrumbItem control which is a templated ContentControl that has in its default template the typical ContentPresenter and whatever you want to use by default as separator all in a Grid or StackPanel.
The GetContainerForItemOverride generates a new instance of this BreadCrumbItem sets its ContentTemplate to the ItemTemplate property from your ItemsControl derivative (the BreadCrumb control?).
Your BreadCrumb control would also expose BreadCrumbItemStyle property that you assign to the BreadCrumbItem you create during GetContainerForItemOverride.
For completeness you may need to also implement the other *Container*Override methods in your BreadCrumb control.

WPF - Dynamic tooltip

I have a class ToolTipProvider
which has a method
string GetToolTip(UIElement element)
which will return a specific tooltip for the UIElement specified, based on various factors including properties of the UIElement itself and also looking up into documentation which can be changed dynamically. It will also probably run in a thread so when the form first fires up the tooltips will be something like the visual studio 'Document cache is still being constructed', then populated in the background.
I want to allow this to be used in any wpf form with the minimum effort for the developer. Essentially I want to insert an ObjectDataProvider resource into the Window.Resources to wrap my ToolTipProvider object, then I think I need to create a tooltip (called e.g. MyToolTipProvider) in the resources which references that ObjectDataProvider, then on any element which requires this tooltip functionality it would just be a case of ToolTip="{StaticResource MyToolTipProvider}"
however I can't work out a) how to bind the actual elemnt itself to the MethodParameters of the objectdataprovider, or b) how to force it to call the method each time the tooltip is opened.
Any ideas/pointers on the general pattern I need? Not looking for complete solution, just any ideas from those more experienced
Create a new user control which functions as a tool-tip view factory.
Use your control as the tool-tip, passing any data you need for the factory to your control using binding (e.g. the data, the containing control, ...)
<AnyControl>
<AnyControl.ToolTip>
<YourToolTipControl Content="{Binding}" />
</AnyControl.ToolTip>
</AnyControl>
Not calling myself an expert, but I'd probably attempt such a feature with an attached property. This would be attachable to any element in your UI and you can specify an event handler that gets access to the object to which the property is being attached as well as the value passed to the attached property. You can keep a reference to the element to which your attached property was attached and you would then be able to change the ToolTip whenever you want.

Categories