I'm looking for something like a ContainerUIElement3D which supports the ItemsSource property and an ItemTemplate property which I can use within a Viewport3D. My aim is to be able to write something like:
<ItemsControl3D ItemsSource="{Binding Path=MyItems}">
<ItemsControl3D.ItemTemplate>
<DataTemplate3D>
<!-- My template which defines the binding to each item. -->
<DataTemplate3D>
</ItemsControl3D.ItemTemplate>
</ItemsControl3D>
I'm looking for tips on how to implement this. The first tricky part is to create a DataTemplate3D which can construct the Visual3D needed to add to the ItemsControl3D.
I've been using .NET reflector to browse through the implementation of ItemsControl and DataTemplate, but I soon realised that I don't have a deep enough understanding and enough time to come up with a solution on my own.
There's an implementation of ItemsControl3D made by DKT # Pelebyte blog. I haven't tryed it. But I sure will.
Regards
Related
I have developed a 3D-engine in C# and I want it to be usable from within a WPF application through classes that can be used just like any other WPF Control.
First implementation
I created a Panel (let's call it EnginePanel) that extends the Grid class, and a set of controls to put inside like SceneNodeControl, GeometryControl, etc... These controls inherit the FrameworkElement WPF class.
For the SceneNodeControl, I exposed a Children property (UIElementCollection) and overrode that Logical/Visual management methods so that they look inside this collection.
I also overrode the ArrangeOverride and MeasureOverride methods so that we call Arrange/Measure on each child of the SceneNodeControl and then return a constant Size of zero pixels.
This implementation works and allows me to use ItemsControl, ContentControl and DataTemplates to populate my scene graph with a classical MVVM pattern.
Problem
My problem is that if I create a massive scene graph with hundreds of SceneNodeControls, the application dramatically slows down.
A quick check with the Visual Studio Profiler informed me that the Measure method from SceneNodeControl is responsible for 80% to 90% of the CPU usage (in terms of time spent).
OK, no problem. What I have to do is to remove these calculations that are too heavy and moreover useless in my case.
Solution 1
I tried to simply remove the call to the Arrange/Measure methods on the children of the SceneNodeControl.
This does not work. As specified in MSDN, the implementations of these methods MUST call the Arrange/Measure on the children.
Solution 2
Inherits the FrameworkContentElement. Indeed, this class does not have layouting algorithms.
But it does not have any Visual tree management, which makes it unusable with ItemsControls, ContentControl and DataTemplates.
Other solutions
I don't have other solutions... so this is why I'm here now!
The question is How to avoid WPF to make Arrangements/Measurements on my own controls?
Thanks!
Edit
Solution 3
I found another solution to my problem (but it produces more and more questions).
My controls can inherit the DependencyObject class. In that way, it should be possible to use the DataContextes from other WPF controls and more generally their DependencyProperties.
Problem number 1: I cannot use the existing DataTemplate, ItemsControl and ContentControl classes, but I probably can reimplement them...
Problem number 2: I cannot tell a DependencyObject to be a 'parent' of another DependencyObject. I found some hacks that 'reflect' this class and expose hidden members to try to manage the InheritanceContext and InheritanceParent. But since no one seems to do that and since Microsoft obviously don't want us to use it, it's really hard...
I will probably open a new question about this second problem. (Edit: It's here.)
Edit: to focus my question
What I want is writing something like that:
<controls:SceneNodeControl NodeName="Root">
<ItemsControl ItemsSource="{Binding SceneNodes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:SceneNodeViewModel}">
<controls:SceneNodeControl NodeName="{Binding Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</controls:SceneNodeControl>
and, at runtime, don't execute Measure/Arrange algorithms on the SceneNodeControls but build their Logical/Visual trees.
And here is my little test project.
If you don't want measure and Arrange affect the logic tree starting in NodeSceneControl and don't want to render it, just set its Visibility property to Visibility.Collapsed. This way, this node will be left out of the layout processing.
I am new to Silverlight, but I couldn't find anything about this when I googled it.
I have a button that I am trying to set the style programatically. I have the style defined in a XAML file and I want to pull the style into C# so I can dynamically create a button and assign it this style. So far, this is what I am trying:
button.Style = (Style)Resources["CloseButtonStyle"];
However, it just makes the button have no style. Is there an easy way to do this? I feel like this should be obvious, but I can't get it to work.
You are assuming that your Resources property on the current object is the one that contains the defined style. However, I assume, given the symptoms of your issue, that CloseButtonStyle is actually defined further up the control hierarchy.
Instead, you need to traverse your control hierarchy until you find the resource (or if you know the object that defines it, just refer directly to that object). Unfortunately, Silverlight doesn't include FindResource call like WPF, but it's not too difficult to implement your own.
I can call button1.Style = (Style)Resources["NonExistentKey"]; and it makes my button have no style at all as well, point being that the resource is probably not being found, you won't get an exception.
You directly access the Resources property, but is the style really in the immediate resource dictionary of your Window/UserControl/whatever-you-have?
Before I begin here is a reference to how I implemented a template selector with Silverlight.
http://geekswithblogs.net/tkokke/archive/2009/09/28/datatemplateselector-in-silverlight.aspx
Everything works great. But the solution just doesn't work in blends making things more difficult to visualize overall. Is the correct work flow to just create a UserControl from the contents and embed it inside the Resource Dictionary to make it blendable, or is there a better way to do this?
Either way, I'm asking this question and posting the Template Selector solution at the same time, because I found it useful. Better solutions are very much welcome.
fyi.. sl4,.net4, latest blends.. all the new toys.. using mvvm light(little relevance).
I would recommend you go with the the following kind of implementation: DataTemplateSelector on CodeProject.
The drawback of the link you posted is that the location and name of the templates are hard-coded in the ContentControl's implementation. With the approach provided in the article I link to, the data templates are accessed in-line, or by regular {StaticResource} references (which means more flexibility), and on top of that, Blend knows what to do with that.
(honestly I searched and read all the 'related questions' that seemed relevant - i do hope i didn't "miss" this question from elsewhere but here goes...)
There are two different ways (at least) to set the DataContext. One can use XAML or one can use the code behind.
What is the 'best practice' and why?
I tend to favor setting it in XAML because it allows a designer to define collections on their own but I need 'ammunition' on why it's a best practice or why I'm crazy and the code behind is the bomb...
A third way you might look at is using a locator service. I usually have one class that is responsible for the creation of all my DataContext(VM's in most cases for me) and I create an instance of that class in the App.xaml Resources. Then I bind the DataContext in the XAML of each individual page.
i.e.
<Page DataContext="{Binding ViewModel,Source={StaticResource Locator}}" >
I think it depends on what you are setting the DataContext to, and ultimately personal preference.
I personally always do it in the code behind of my views because I find it overall cleaner, and it was how I was taught MVVM. Another thing to keep in mind is, there are times you may need to change your datacontext depending on what you are working with. If this is the case it's much cleaner/easier to do in the code behind rather than in XAML.
As you can see by the answers so far opinion is divided. In truth there is no best practice (I do get bee in my bonet about discusions of "best practice" in the Silverlight world, its way too young for best practice to be truely known.)
The reality actually is that you can't set the "data context" in Xaml. Unless you actually construct an object instance like this:-
<UserControl>
<UserControl.DataContext>
<local:MyDataProviderThing />
Ultimately something external has to assign either the DataContext property directly or indirectly via another property or via binding (as in Stephan's answer). Its this external context which is dictates whether it makes sense to do it in Xaml or not. Many MVVM solutions use a binding in Xaml, in some cases simply to avoid there having to be any code at all in code-behind rather than it truely being "better". Others set up the DataContext in code using a base class that your control derives from.
DataContext of the user control/view I assume? One advantage of setting data context in the code behind is the availability of dependency injection. Your DI container can take care of any dependencies for you dynamically at run-time.
With this pattern, I frequently set a view's Blend design DataContext in xaml using d:DataContext. The "design version" can provide mock data for use in Blend, while the true implementation is resolved at run-time.
I want to add/remove some part of XAML dynamically i.e. from code behind file in C#.how to Add any specific XAML string on specified location (means under some tag) from .cs file. Please help.
XAML is xml you can use XmlReader and XmlWriter or any other of the XML serialization mechanismn of .NET to write/read XML (XMlDocument is probably the best approach here to modify existing xml). ALso there are the XamlReader and XamlWriter class that allow ou to (de)serialize any object graph from/to XAML automatically. If you can use .NET 4.0, you have even more fine grained possibilities to athor XAML because it has a new XAML stack. Use this as a starting point.
What is it that modifying the XAML will do for you?
If you just want to change the appearance of your WPF application (perhaps by adding some more content at certain locations), it will most likely be easier to do this by referencing the objects in question. So, if you need to add some text to a button, name the button with x:Name="myButton" and in code set: myButton.Content = "Click Me"
XAML is really a technology for constructing object hierarchies. Pretty much every element in the XAML corresponds to a .NET CLR class. When loaded, these classes are instantiated nd populated according to the attributes used in the XAML. Once loaded, the XAML has finished it's job and is essentially unloaded/unavailable.
You might need to do something beyond this, but from your brief question it doesn't seem like it. I would just work on the object model and leave the XAML be.