WPF - CAL - Multiple parents for single instance of control? - wpf

I am working on a PRISM / CAL solution, but the problem may be WPF specific:
If I create one instance of an control (e.g. TextBlock) and add it as child to a StackPanel, there is no way to add it as "child" to another StackPanel (parent already set error). I kind of understand the reason (it also occurs when using the RegionManager).
But what is the suggested way if a visual control is very complex and should be created only one time and used in two places? I agree that is does not really make sense to show an identical control 2 times on the screen, but there might be cases where it is useful (e.g. an "Close All" Button).
I know that in the button case, I should just create two buttons both databound to one ICommand. But does this rule also apply with much more complex controls (always create new instances)...
I stumbled on this problem when creating a layout switcher, which creates the button list and the stack panel for each GUI seperately, but uses a static ObservableCollection of buttons as source (which causes strange bugs)..
Any ideas on this topic?
Chris

This is normally handled by templates. That is, you abstract out the data into a particular type, and associate a template with that type. Then you place the instance of that data any number of times into your visual tree and have WPF render it with the template.
In short, don't add a TextBlock to your StackPanel. Instead, add an instance of your data type (eg. Customer) and associate a DataTemplate with the Customer type. There is no way to parent the same UIElement in multiple places.

You can add your control (or collection of controls) as a resource and refer to them via binding in your controls. This will implicitly create a copy (they will be Freezable and WPF will copy them).
Generally you should be using DataTemplates as Kent suggests, but if you have a special case, this will likely work.

Related

UserControl, ContentControl and MVVM

I'm kind of a beginner with the WPF platform. I've done a few Windows Forms apps that were very basic and now I'm working on a much more complex app for my current work.
I'd like to implement an MVVM model, but I'm getting lost in the different articles on how to do so.
Here's a screenshot of the app interface:
The section on the left is a ListView containing 6 sections that correspond to different UserControl. I would like the section on the right to display the UserControl that corresponds to the selected Item.
Each UserControl is stored in a separate XAML file.
By looking online, I found that I should use a ContentControl in my MainWindow, but every attempt I've made has been unfruitful. I know there's more than one way to skin a cat.
Which method would you use? Do you have any concrete examples or sources where I can find how to make it work?
The only difference between UserControl and ContentControl is the OnCreateAutomationPeer method. This method is responsible for UI automation.
Although this method is rarely used in practice, it is customary to use UserControl to represent some complex data types.
A typical use for a UserControl is to retrieve data (in normal CLR types) through the data context.
And the Content property specifies (using XAML) a visual tree to represent that context.
And each such UserControl is declared as a derived type (just like a Window).
If necessary, additional properties (CLR and DP) and other members (event handler methods, for example) are added to such a UserControl.
The base class ContentControl itself and others of its successor are used somewhat differently.
The data in them goes directly to the Content property.
And their visualization is set by the data template in the ContentTemplate property.
While DataTemplate's can be quite complex, they are usually much simpler than the XAML markup of the UserControl.
And, besides the task of visualization, you cannot add additional logic (properties, fields, methods).
Here's a photo of the app interface: ...
In this UI, I don't see where the ContentControl can be applied.
On the left is a navigation bar consisting of buttons.
It is usually implemented directly in the Window from an ItemsControl or ListBox.
On the right (while an empty area) is the region for the page content.
Usually, when you click on a button in the navigation bar, the corresponding UserControl is set to this region.
At a lower level, deeper in the visual tree, for smaller elements, it is quite possible that a ContentControl is needed.
P.S. Just in case, I will clarify, in view of the comment below.
By area for pages, I do not in any way mean the use of Frame + Page.
This is a very specific pair and it is extremely rarely justified to use it.
In combination with MVVM, its use is even more difficult, since this pair does not support DataContext inheritance.
And this is the main way for the View to interact with the ViewModel.

WPF Combobox with auto-complete/auto-filter?

I am eager to find some solid (free, Open Source, or tutorial/example) code to make a WPF Combobox do autocomlete/autofilter as the user types. But everything I've tried so far has had some sort of problem...
A Reusable WPF Autocomplete TextBox came close, but I can't get it to work with more than one filter (more info here).
WPF autocomplete textbox/combobox doesn't work for me because it inherits from UserControl, and thus doesn't support the DataTemplates I need (for showing/selecting the value of one property for an object with multiple properties).
Automatically Filtering a ComboBox in WPF didn't work because it doesn't seem to ever find the EditableTextBox portion of the inherited ComboBox code (via (TextBox)base.GetTemplateChild("PART_EditableTextBox") which seems to always returns null).
Building a Filtered ComboBox for WPF just gets stuck in a refresh loop then overflows the stack after I type just a few letters.
Other things I've considered:
I know that Windows Forms' Combobox control has AutoCompleteMode and I could embed it in WPF, but I can't imagine it would play very well with my WPF data bindings.
Perhaps it is too complex and I need to simplify, maybe by building one-dimensional (single-property) ObservableCollections for the ComboBoxen... However, the challenge of applying multiple filters (one set by another control's value, and one from what the user is typing) to multiple controls using different views of the same DataSet would require a ridiculous amount of processing power to destroy and rebuild the list every time the user types a character!
So... I'm at wit's end. Any suggestions?
If your Combobox has some data source attached to it ,
just make
1-IsTextSearchEnabled = true.
2-IsEditable = true.
you are good to go
Try this one:
http://blogs.windowsclient.net/dragonz/archive/2010/02/23/autocomplete-textbox-control-for-wpf.aspx

Access Elements inside a DataTemplate... How to for more than 1 DataTemplate?

I've got 2 DataTemplates defined for a Listbox Control. 1 Template is for the UnSelected State and the other one is for the Selected State(showing more detail than the UnSelected State).
I followed the example here:
Link
about how to access the Elements inside the DataTemplates from Code behind.
I get it right, but it only finds and returns an element of the UnSelected DataTemplate. But when i search for an element in the Selected DataTemplate i get a NullReferenceException.
What could i be doing wrong?
Setting keyboard focus might be one reason you need to access the datatemplate elements. MVVM will not solve that issue and the FocusManager doesn't set keyboard focus.
What you are doing wrong?
I would say what you are doing wrong is trying to access elements inside the DataTemplate from code-behind. Naughty, naughty!
All joking aside, 99.9% of the time I see someone trying to access an element inside a DataTemplate from code, it is because their application is poorly designed, with no (or few) bindings and no view model at all. Many beginners tend to store their data directly in UI elements rather than using a view model. I think it is because their minds have been corrupted by experience VB, WinForms, and ASP.NET where it was the "normal" way to do it. There are a thousand reasons to use a view model and bind your data instead of storing them in UI elements. Look up "model view view model" online for more details.
Now to answer your question:
Any given ListBoxItem can only have one DataTemplate at a time. This is because its ContentPresenter has only one ContentTemplate property, and this property cannot have two different values.
Because of this, the visual tree under a ListBoxItem will always be generated from one a specific template, not a combination of several templates. If you change the ItemTemplate of the ListBox or otherwise update ListBoxItem.ContentTemplate, the visual tree produced by the old template will be thrown away and a new one built.
Let me say that again: If you change data templates, the visual tree produced by the old data template will be thrown away and a new visual tree built.
You can have a hundred data templates defined and usable on a given ListBoxItem, but only one at a time can have a visual tree instantiated for it. And these are the only elements that actually exist as part of the visual tree. All other templates exist only as templates - there are no actual elements created for them.
To put it another way: It is meaningless to ask about how to find elements in two different visual trees instantiated by two different templates on the same control, because a single control cannot have two different templates active at the same time.
Hope this clears things up for you.
Final advice: Do read up on MVVM, and stop trying to access elements inside DataTemplates ASAP. However if you think you might be in that 0.1% who actually do have valid reasons to access elements inside templates, write back with your actual reason for wanting to do so and maybe I can provide further guidance.

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).

Loop through UserControl in WPF

Hey, I was wondering if it was possible to loop through several WPF controls. So lets say I have a control that I want rendered (with different data each time) 10-20 times depending on what it has.
The only alternative I found was to manually create 20 of these user controls and hide the ones I was not using.
Is it possible to loop them?
I assume you're already using data templates and you're asking how to loop through the objects created to represent your data from the DataTemplate. Am I right?
In order to do that you need to use the VisualTreeHelper.
You're probably going to have to refine your question.
What do you mean by "loop through?"
When you say you want to render a control "10-20 times", do you mean you have one control you need to change 10-20 times or 10-20 controls?
You might be interested in looking into DataTemplates and ItemsControls. You can bind the ItemsControl to an ObservableCollection containing different types of objects, then define different DataTemplates for each type of object contained in the collection. The ItemsControl will render the appropriate control for each object contained in the ObservableCollection.

Resources