ListBox on Canvas: overlay multiple canvases or use CompositeCollection? - wpf

In wpf with mvvm I use a ListBox with Canvas as ItemsPanelTemplate and DataTemplates to customize appearance.
I would like to improve performance by first adding all items of type 1 to the drawing, then all items of type 2.
I could create two ListBoxes both with Canvas as ItemsPanelTemplate and they would be overlays.
Panning and scrolling could be synchronized by means of bindings.
This way I can raise PropertyChanges for both lists independantly from each other.
Question: do you have experience whether overlaying canvases is good or bad for performance?
I an not sure whether this is also possible using a CompositeCollection for the ItemsSource of one ListBox. Or for that matter give both types a common subclass and stay with ObservableCollection.
Question: do you think that somehow a list with CompositeCollection can be given separate PropertyChanges for different parts of the Collection?
EDIT:
Suppose I have a great number of points, lines, labels for the canvas, each of a different type, however with a common base type. I select the DataTemplate using DataType: DataType="{x:Type my:Point}", DataType="{x:Type my:Line}" etc.
First as quicly as possible I want the user to see the lines. I raise PropertyChanged("Lines") and the ListBox+Canvas for the lines is visible.
In a backgroundworker I raise PropertyChanged("Points") and the ListBox2+Canvas2 for the points is visible.
When done in another backgroundworker I raise PropertyChanged("Labels") and the ListBox3+Canvas3 for the labels is visible.

There's a much simpler solution using basic Object Oriented Programming. Create a base data type and make all of your data objects extend from it. It could be empty, but if nothing else, you could implement INotifyPropertyChanged in it so you don't have to in each of the other data types.
Then you simply add a property of type ObservableCollection<BaseClass> to your view model or code behind and data bind that to the ListBox.ItemsSource property. As long as you don't set the x:Key values on the different DataTemplates, then WPF will implicitly set them to the relevant data type objects when it renders them.
So you can put all of your different data types in the same collection. Then you can add your first type in and wait for however long and add some of a different type, or whatever order you feel like.
UPDATE >>>
In response to the edit in your question, I don't quite understand the reason for you trying to use the INotifyPropertyChanged interface to show the items, type by type. If you have the base class collection that I mentioned above, then you simply add the instances of the first type to the collection first, so they'll appear first. When you want the next type to appear, just add them into the collection and then they'll appear and so on. The ObservableCollection will take care of that.

Related

Hide Elements in WPF TreeView

i have the following scenario:
I have a ViewModel with hierachical elements to display in a TreeView. So far so good. What i want to do now is hide/remove elements from the TreeView according to some property set on a ViewModel-Element, like IsConfigurable or such.
If i disable die DataTemplate, the element is removed, but also all child-elements, which is not what i want.
Is that even possible?
Greets,
Jürgen
That sounds somewhat strange, but nevertheless...
You should consider that your application shall remain test and debuggable.
Your model contains the orginal data (collection) as it is - no meddling here. In your ViewModel, the object that you are binding to, you can calculate the transformation as you want to display your hierarchy. This approach has the benefit, that you can "easily" test/debug your transformation. Now bind your TreeView to the calculated hierarchy without obscure experiments. If properties in your ViewModel (you mentioned IsConfigurable or whatever) change, you know when to re-calc your bound hierarchy.

When not to template a WPF ListBox...?

I'm looking to represent a collection of different but related data types and give the user the chance to edit these. I can't represent them in a grid because each type is different and therefore doesn't lend itself to a grid layout.
e.g.
Type1 - properties are From, To, Threshold, Enabled
Type2 - properties are From, ExecutedPercent, Benchmark, Enabled
etc
These types are related but different so I'm thinking of creating a tool bar with the types along the top. When the user selects Type1 I generate the UI using a custom ItemTemplate on a ListBox, same for Type2. I am therefore swapping out the ItemTemplate at runtime and changing the data source.
Questions:
1. Does this sound like a reasonable approach?
2. Does it make sense to item template ListBox?
3. Are there any other controls I should think about templating here? It seems to me that ListBox is about the perfect candidate for any kind of List source when all the items need to be displayed.
Thanks in advance
In order to handle different types of items you can use ItemTemplateSelector which will be more clear WPF solution.
If you do not need having selected item in listbox and only need to display items then you should use ItemsControl instead of ListBox
you can use a datatemplateselecter so you dont have to set the itemtemplate when the type is switched just change the datasource.

wpf - bind label widths to calculated length property

If I had a label on a view that I wanted to have the width equal to the width of two columns in one of my grids on the same view, how would I set up the binding without using a converter? Should I use properties to preform my calculation and store a value? It is my intention that if the view's grid size changes then this label's size will also change to match the new width of the two columns.
And where should I put this logic? I am trying to follow MVVM pattern but I see that a lot of threads about "converters in MVVM" say to put the logic into the viewmodel.
I tried to implement this behavior with dependency properties on my view since my viewmodel technically has no knowledge of my view (so how would my viewmodel know how wide my columns currently are?). This goes against what I have read online though. When implementing this behavior I noticed that I cannot reference my columns by name unless my property is not static, but dependency properties are static so I am not sure how to shuffle my values around without creating yet more properties to hold values.
Can someone provide help here? I feel like i'm overcomplicating this. I just need this label to sit over these two columns however they stretch. It just provides a visual grouping of related fields in the grid. Once I can do this first one, the other two should be equally similar.
My rule of thumb is if it's "View" related then keep it away from the ViewModel. From your description this sounds like it's purely view related, so I would just use logic in either the codebehind or a converter.
Now what I don't understand is why you are reluctant to use Converters. With converters you certainly don't want to store business logic that is going to lead to confusion or pain points for refactoring, but if you have some value that needs to be converted for a specific view operation then Converters are exactly what you should be using.
So my advice is Converters ... if it's View related then feel free to use Converters and Codebehind ... in fact you should use them and not the ViewModel.
Does that help?

Silverlight: binding an observable collection to different usercontrols conditionally

I'm new to Silverlight 4 and having a tough time googling this one since I'm not terribly familiar with the terminology involved. Can someone point me in the right direction?
I have an observable collection that I want to represent in an ItemsControl list. The type of the collection is a class that- for simplicity's sake- let's call PersonInfo. Each PersonInfo has a string property Name and an observable collection PhoneNumbers. Everything works fine when I tell the ItemsControl's DataTemplate to use "UserControl1" for visualizing the data- the bindings work.
My problem is that- for this theoretical example- I want to base the control used to display the PersonInfo on certain values in the Name propery. So I want to use UserControl1 for any entries named "Joe", and use UserControl2 for all others. I've found IValueConverter stuff, but that doesn't seem to help with selecting the control type used to visualize the data.
Sidenote: UserControl1 and UserControl2 show data in a similar way, but there are some differences within their complicated grid layouts that forced me to create 2 separate usercontrols. If anyone knows how I could build multiple layouts into UserControl1's xaml and then switch between them at runtime via a property binding, that would probably let me sidestep this issue altogether...
Can anyone recommend a general strategy for solving either side of this problem?
Thanks in advance!
I’ve solved a similar dilemma by using an IValueConverter in an unusual way: I created a "VisibilityConverter" that tells a control whether it ought to appear. In the case of your example you would have two of them: one Convert method would
return ((PersonInfo)o).Name == "Joe" ? Visibility.Visible : Visibility.Collapsed;
and the other would do the opposite. Then bind UserControl1's visibility to one VisibilityConverter and bind UserControl2's visibility to the other and violà, they swap out based on the data.

How to display in each ListBoxItem textblocks with binding to a filelds of a different tables

Greetings to all and sorry for my English!
I have a ListBox, it's ItemsSource = myClientsList.DefaultView. The Items of ListBox have a template (ControlTemplate), that is defined in a in a separate resource file.
Every Item contains a little TextBlock's, Text -property of each have a binding to fields of my Object myClientsList.
I need to add in a this item template more TexBlock's and each of them must have binding to fields of another my class myOrdersList. - (So I wish to view on each line of ListBox information from different tables of my database - this is a question).
Problem in that that ListBox's ItemsSource have a link to object myClientsList and I cann't set myOrderList to ItemSource of same ListBox. So i must find a way to specify TextBlock.DataContext wich inside ControlTemplate or how it's possible to solve this problem in another way?
p.s. I'm a new in .Net and WPF and probably have a mistakes in my explanation - sorry for it.
It sounds like you have a DataGrid type of display and want to add more columns in order to display the order information for a given client. If this is the case, you are going to have to do a couple of things. First, you will need to create a composite object that stores information for both entities into a single object (so each row of your control has all the data it needs to display). Secondly, I would recommend using an actual DataGrid control to display rows instead of templating a ListBoxItem. The ListView with a GridView built into the framework isn't great, so I would recommend the WPFToolkit's DataGrid for a free option.
There are two issues here, if I've understood the question: how do you create a single collection containing both Clients and Orders, and how do you display Clients and Orders in different ways within the same ListBox?
Regarding the first, you can do this using a CompositeCollection.
Regarding the second, define two DataTemplates instead of a ControlTemplate. As the key of each DataTemplate, use the type of the object it is going to present e.g.
<DataTemplate x:Key="{x:Type local:Client}">
Alternatively, use ItemsControl.ItemTemplateSelector to explicitly point at different DataTemplates depending on the type of item. Ot if you really have to use ControlTemplates, check out ItemsControl.ItemContainerStyleSelector.

Resources