Dynamic control creation in WPF - wpf

I'm working on a project where I have some hierarchical data that I want to be able edit through a fancy WPF control.
The data structure is essentially an expression tree. Each node can be a different Expression type but inheriting from the same base class. These different types need to have their own way of editing them.
My thoughts are that I would use the WPF TreeView control and then dynamically add editor controls for each type of Expression. I have only a basic understanding of WPF's data binding and the MVVM pattern so I'm not sure if this is possible to do or even where to begin. Any pointers or guidance would be greatly appreciated.

It sounds like what you're looking for is the HierarchicalDataTemplate class.

Related

How to change element in xaml that are in visual tree

I'm new to WPF and tyring to uderstand the best way I can modify any given control attributes. What I was trying to achieve is to show tooltip for a cell. Yes a quick google and can see xaml of how to do it. But I want to understand how can one learn to figure out this out using some tool.
I came across Snoop that can show visual tree of a control very easily (CTRL+SHIFT Mouse over). What I'm trying to understand is if one knows of visual tree, how can one change it? For example, let's say I use WPF DataGrid and bind it to a source and display column using DataGridTextColumn.
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}">
Now let's say I want to show tooltip for each cell. So I fire up Snoop and CTRL+SHIFT mouse over the cell. Snoop shows me that its a DataGridCell that is using Border and withing it ContentPresenter which ends up using TextBlock to show the value. So that means that if I can somehow access that textblock, I can set its tooltip property using binding. Issue is that I don't know how I can access it in xaml.
In other words, knowing a visual tree, how can one access it in xaml for any given control. This will also be very handly for 3rd party controls.
Thanks
Your'e asking quite a bit here, and i'm not sure I completely understand your intention, so I hope I got this right. Your'e asking if you can access the complete visual representation of each control and change it using xaml. The answer to that is yes, but you shouldn't.
I'll get to what I mean in a bit, but first I'd like to clarify some concepts, since i'm not sure you're using them correctly.
XAML:
Xaml is the declarative markup representation of your views and nothing more. Xaml syntax directly corresponds to it's respective classes and their properties. Xaml maps tags to classes and attributes to properties. It's a small distinction, but it's important to think this way. Everything you can do in xaml you can also do in code (although it would often be much more work). Again: xaml refers to markup code only.
<ClassA PropertyA="Value">
<ClassA.PropertyB>
<ClassB />
</ClassA.PropertyB>
Default property value
</ClassA>
Logical tree:
The logical tree is the runtime representation of your xaml code. it consists (mostly) of the controls you set in your xaml files.
Visual tree:
The visual tree is the visual representation the logical tree. It contains much more since it contains the concrete visual representation of everything displayed in your view. Most of the logical tree can't be directly displayed. WPF uses Data and Control Templates together with Styles to determine exactly how each object is supposed to look. In case of data templates that can also mean simple data objects and not only WPF controls.
Now for your question: so can you access the concrete visual representation of each control?
Yes, but you'll have to use control templates to manipulate it's visuals. Also, control templates are usually applied to control types and not specific controls, so you'll have to deal with that as well.
And that's why you shouldn't access it. The xaml representation usually gives you all you need to modify your control, and even if you do use templates you shouldn't change every last piece of it. Templates are used to style a control, so only write enough to show it as you wish. There's no need specify everything.
However you can access the entire visual tree more easily using procedural code, if you use the VisualTreeHelper class (that's how snoop does it, by the way). Using it you can traverse the visual tree and access all it's classes and members. If you really want to access every single visual object you'll do it much more easily with the VisualTreeHelper.

Extending user controls in WPF

I have built a User Control composed, as usual, of a XAML part and a code-behind part. Now, I need to create another User Control which shares some of the functionalities of the former, but which has different looks and might also have additional features in the code-behind.
My first idea was to create an interface to gather the common functionalities of the two types of controls. Is this the right way to go? And how would I manage the different XAML parts I should have? Any advice is welcome.
I would like to add another contribution which I think might be useful to others encountering my same situation.
One other possible solution, which in my opinion is suitable if the controls you are going to create are not particularly complex, is to create a base User Control containing the common features that you want to share: such control will be written entirely in C#.
This, in fact, allows inheritance in User Controls composed of both XAML and code behind. In the XAML of the inherited control, rather than having
<UserControl> ... </UserControl>
You will have
<MyProject: MyBaseControl x:Class="MyProject.MyExtendedControl"> ... </MyProject: MyBaseControl>
and then in the code behind you will also need to specify the following:
class MyExtendedControl : MyBaseControl
Hope this helps.
User controls don't lend themselves well to inheritance in WPF, you can do some hacks to make it work, but overall you'll probably be better off using a Custom Control instead. It's easier to specify different XAML for inherited controls using this technique. The easiest way to get started with a custom control is to add a new item to your project of type "Custom Control (WPF)" and it will add the control and the XAML gets added to Themes/generic.xaml for you.
To inherit from this control, the easiest way is to add another new Custom Control (WPF) and then change the code behind to inherit from your parent control instead of Control.
There are a number of ways to split up the pieces to make them easier to work with.
MVVM, as mentioned in a comment, relies upon Data Binding to separate the input controls from logic. By setting the appropriate class which implements INotifyPropertyChanged into the DataContext of you control, you can change the behaviour. Your DataContext class or ViewModel could implement Visibility properties to show and hide different parts of the input if the differences are not too great between the uses.
Another way to break apart functionality is by Aggregation. See StackOverflow 269496
You could build smaller controls that implement common functionality and then build larger special purpose controls by combining the smaller controls (i.e. aggregating them) to make the larger control. Aggregation will work for both the code-behind and the Data Binding approaches.

When to use UserControl vs. Control in Silverlight?

I'm just getting my feet wet in Silverlight, and don't really understand the differences and pros/cons of creating a UserControl vs. creating a Control for the same task (as in when you right click on a selection in Expression Blend, for instance).
It seems like selecting "Make Into Control" just creates a new template for the base type you specify, whereas creating a UserControl creates a whole new base class. Is that correct?
In this particular instance, I'm creating a custom text box control that only takes numbers, and divides itself into 3 sections, storing 3 values into separate properties as pictured below. In this particular case, which would be best?
UserControls are meant to be a composite control - basically a bunch of other "controls" grouped together to work as a single, cohesive unit.
Custom Controls, on the other hand, are intended to be used as a single control. Think of the basic controls in the framework, such as TextBox or Button - if you were implementing something like that, you'd want a Control. (This is less common than UserControls, especially in WPF, since you can use templating on base class controls to accomplish quite a few things where you'd need custom controls in other frameworks). A custom Control is all about defining new behavior for a single "control."
If you consider your control to be a group of three text boxes then a UserControl would be appropriate, but if your control will still essentially be a TextBox then you should extend the existing control with "Make into control."
It sounds like you need a UserControl to me.
Dov, I think you've answered your own question with your update. Custom Controls are most useful when you want to make a control that supports templating. Otherwise they are useful when you are inheriting from other controls to cleanly add functionality (TextBox -> PasswordTextBox).

Should I be using Expression Blend to design really dynamic UIs?

My company's product is, at its core, a framework for developing metadata-driven UIs. I don't know how to characterize it less succinctly than that, and hope I won't need to for purposes of this question, but we'll see.
I've been trying to come up to speed on WPF, and have been building UI prototypes here and there, and recently I decided to see if I could use Expression Blend to help with the design of these UIs. And I'm pretty mystified at this point.
It appears to me as though Expresssion Blend is designed with the expectation that you already know all of the objects that are going to be present in the UI at design time. But our program generates these object dynamically at runtime.
For instance, a data row might be presented in a horizontal StackPanel containing alternating TextBlocks (for captions) and TextBoxes (for data fields). The number of these objects depends on metadata about the number of columns in the data row. I can, pretty readily, write code that runs through a metadata record and populates a StackPanel dynamically, setting up the binding of all of the controls to properties in either the data or metadata. (A TextBox's Width might be bound to metadata, while its Text is bound to data.)
But I can't even begin to figure out how to do something like this in Expression Blend. I can manually create all these controls, so that I have a set of controls that I can apply styles to and work out the visual design of the app, but it's really a pain to do this.
I can write code that goes through my data model and emits XAML for all these controls, I suppose, and then copy and paste it. But I'm going to feel really stupid if it turns out there a way to do this sort of thing in Expression Blend and I've dropped back and punted because I'm too dim to figure out the right way to think of it.
Is this enough information for someone to try formulating an answer?
I think expression blend is a very good choice ESPECIALLY if you want to design dynamic, datadriven UIs. You can use Blend to desgin DataTemplates that define how a single dataobject is to be presented to the screen. For example, if you have an object of type Person you can define the controls like textboxes, border etc. that then are to be generated automatically for each Person in your list.
You can then fill your ItemsControls (DataGrid, ListView, TreeView ...) with those dynamic databojects and WPF knows how to render them. If a Persopn is removed form the list, the generated visual item will be removed too. This is just a simple example the whole notion of dynamic data is deeply baked into WPF and you can access these features using blend.
To be able to design the datatemplates in expression blend you need to provide sample designtime data.
Also to be effective with all this it is of high advantage if you stick with the MVVM design.

WPF Load Control question

I'm doing some stuff in WPF.
I have a ComboBox with many Types. After selecting a concrete type, I want to be able to Load a particular UserControl (with many TextBoxes etc.) respecting the type in a defined region on my WPF Window.
How to do that? Is there anything like
LoadControl() and load it into a PlaceHolder in ASP.NET? And what's the best way of doing this?
Thanks.
You should create a DataTemplate for each type. See Different item template for each item in a WPF List for more information.
What about:
object o = Activator.CreateInstance(type);
myUserControl.PubliclyExposedContainer.Content = o;
Not really sure why you'd go to the trouble of creating a DataTemplate for each type.

Resources