Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Thursday, September 2, 2010

Changes in x:Array in WPF 4.0

It's been a while, but I thought I'd post the results of a subtle bug I fixed while migrating my app to WPF 4.0. I'm mentioning it because many blogs out there discuss x:Array as a way of creating a static list that you can bind against. There's also a fair amount of confusion because Microsoft started talking about XAML2009 which actually isn't really supported in WPF 4.0 unless you're doing dynamic loading of XAML pages.
What's important to know is that x:Array no longer leaves your Array as an ArrayExtension. Instead, in WPF 4, the array is converted on the fly into a CLR native array of the type your specify in the Type argument.
So if you define something like this in your control Resources block:
<x:Array x:Key="WidgetList" Type="{x:Type local:Widget}" ... />
Then be aware that the result is a Widget[], not an ArrayExtension object.
The practical result is that if you bind against list, say as the ItemsSource in a ListBox, then you no longer should or can add "Items" as the sub-Path.
Before ( < 4.0):
<ListBox ItemsSource="{Binding Source={StaticResource WidgetList}, Path=Items}" ... />
After ( >= 4.0):
<ListBox ItemsSource="{Binding Source={StaticResource WidgetList}}" ... />

Read more...

Friday, June 26, 2009

WPF: Sorting Sets of Simple Strings

I've been doing a fair bit of WPF coding recently, and it's a compelling experience. The thing is, it isn't easy, and I think that surprises some people. Part of the reason for this is that the documentation still feels incomplete, in that undocumented kind of way. But the other reason is that it forces you to think very abstractly, all the time. If I were to think of a decent analogy, it would be one involving cooking: Coding in most UI toolkits is like cooking with lots of pre-made dishes (pre-cooked noodles, microwave dinners, pasta sauces out of the bottle.) Sure, you can make a decent meal, but the results are pretty predictable and maybe not that satisfying. Coding in WPF is like cooking with real ingredients - it can be challenging, and you can certainly mess up the results, but you can also whip up something fantastic.

That said, I thought I might pass along a tip for something that seems like it should be quite easy, but the documentation makes it unclear. I needed to produce two comboboxes for some UI, both of which contain lists of Strings. For one combobox, I needed a custom sort pattern, and for the second one I needed a straight up sort.
I'm finding that there are a bunch of ways to do this. You can create a List<> object that contains the strings, call Sort() on it, then bind it. However, that might not be an adequate solution since you're re-arranging your internal data and you may want to preserve its original order.
The other way of doing this is to apply a SortDescription to the Items list of your combobox or ListView. A SortDescription is pair consisting of a String which describes the property to sort on, and a sort order (ascending or descending.)
Now here's a little tip I just figured out: Most examples explain how to Sort a list of items that are bound to the control, by specifying the property name of the property to sort the content on.
combobox.Items.SortDescriptions.Add( 
    new SortDescriptions("Content", ListSortDirection.Ascending));
But what if your items don't have a sub-property? You may have guessed the answer, but I am hear to confirm that if you pass an empty string as the first parameter to the SortDescription, then it will apply the SortDirection to the Items themselves:
combobox.Items.SortDescriptions.Add( 
    new SortDescriptions("", ListSortDirection.Ascending));
And voila! For the second combo where I needed a custom sort, I simply did my sort on the items themselves beforehand then added them in the right order.

Read more...

Wednesday, April 15, 2009

Jing Screen Captures

Just wanted to give a shout-out to a really nifty WPF program called Jing, from the folks at TechSmith. This screencapture tool is extremely streamlined, allows you capture images and videos seamlessly, and you can post them online at the click of a button. The free version uploads them to the TechSmith hosting site, screencast.com, while the very cheap Pro version lets you upload straight to YouTube. It also supplies an MPEG 4 codec that produces better, smaller video files. And there's a Mac version too!

Other than being a great program, Jing is also a great example of what can be done with WPF. I found out about the program while browsing this very useful WPF resource, Jerry Lin's WPF WTFs, a blog that accumulates WPF knowledge gathered while creating Jing. Check it out!

Read more...

Tuesday, April 14, 2009

iNIN: You Were Poked with a Nine Inch Nail

More Trent Reznor opinions on the music industry and how it should promote itself, as well as a description of the new Nine Inch Nails iPhone app, another experiment in social networking.
The article also describes the dynamics of the App Store, and how, with its low initial entry cost, it is spurring on development of small-scale applications similar to the ones developed in the late eighties and early nineties. John Carmack has even gotten into the act, porting Wolfenstein 3D, the game that put Id Software on the map, to the iPhone.
In fact, he is using an open-source version of his own source code that was originally modified to use OpenGL, and has re-ported that back on to the iPhone. Apparently the project took him 5 days and will make him a bazillion dollars. Check out his blog item on the subject - Carmack is a good writer and his perspective on the gaming industry, not to mention the software industry in general, is fascinating. Wolfenstein, other than being a brilliant money-maker, is also an experiment in usability design - Carmack wants to figure out how to put the FPS on a multi-touch device, and this is his first crack at it. I wouldn't be surprised if he figures it out by the time he releases DOOM.

Read more...

Tuesday, March 24, 2009

WPF: Generalizing using generic.xaml

In my previous post, I went on (and on) about a mechanism for loading generic styles and data templates using a Uri load component scheme. This would load your styles and apply them to the control or window that does the loading.

Since then, I've discovered the somewhat magical and better solution to all this, which is to define a file called \Themes\Generic.xaml in your project root. This apparently tells WPF to tap into its uber styling code and plug in your styles defined here.
I had to dig deeper here, because my templated code was working for my main component, but as soon as I added it to the definition of a floating frame outside of the control (which is a third-party component that I don't have control of) it failed to read the template. Adding the Data template definition to \Themes\Generic.xaml did the trick.

Read more...

Saturday, March 21, 2009

WPF: Loading Generalized DataTemplates in Code

I've been working WPF quite a bit recently and am discovering the ins and outs of this beast. It's nothing if not ambitious.

I personally like it. A lot. I worked with .NET Forms previously and Win32, and Java Swing before that, and this is far and away the most sophisticated UI framework I have ever seen. However, it's still relatively new and documentation (as well as good examples) can be scarce.
One thing that I've noticed when browsing examples online is that most people present ideas through trivial examples - in fact, they repeat the same information through repeated trivial exercises that can be found on other sites. I'll try to avoid doing that, but that also means that I'm going to assume that you know what you're doing. I'm not going to post tutorials or explain basic WPF concepts that are covered in the all the main WPF resources (see another post in the future.) I'm going to post annoying factoids that have halted progress for me personally at work, and hopefully this will help someone out there.
Let's jump in and take a look at generalized DataTemplates in WPF. By generalized, I'm talking about the DataTemplates that set their type via the DataType property. Sampled from MSDN:
<DataTemplate
  DataType="{x:Type c:GreekGod}">
   <TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
</DataTemplate>
Like the Style element, DataTemplate uses the DataType property as a way of hooking itself into the general scope of your application. Style's version of this is TargetType.
Now, here's the problem: Where do you specify this DataTemplate? Where does it go in the project? No one seems to make this clear, or provides a satisfactory answer. The real answer is that this DataTemplate needs to exist in a loaded Resources dictionary somewhere up the logical chain of elements where you expect it to be used.
Everyone assumes a trivial layout for a project. "If you need to create a DataTemplate, then just add it to the Window.Resources element, dumbass." However, this is not very helpful, for anyone who is working outside the standard layout conventions (for instance if you're developing WPF controls for a mixed managed application, and blending them into a Win32 frame.) Sometimes, you don't have the benefit of simply adding the template to a higher level component because, wait for it, the XAML might actually be dynamic. Maybe your application reads in XAML to construct a class at runtime. Maybe popping in a DataTemplate definition here is not such a good idea.
So now I'm scratching my head and going back to the root of the problem - how does WPF know about this template in the first place? If I put it in a loose XAML file in my project, and have it compiled, shouldn't the template be properly registered at runtime? Turns out that that isn't the case. Loose XAML does not a loaded component make, which I thought was interesting, and actually makes a lot of sense. This is something that may not be clear from MSDN: Just because you put a DataType property on a DataTemplate in a ResourceDictionary element without a x:Key in a XAML file that is compiled into your project, doesn't mean that it's actually registered with WPF at runtime. It needs to be loaded into the logical chain somewhere.
XAML is cool, but it's still a static definition of components. If you're going to need to sew anything in, you're best bet is to go back to code.
In my case, the answer lay in dynamically loading the XAML and adding it to my root control's MergedDictionaries set (no handy top-level Window, sorry), in the root control's constructor.
To do this, you create a Uri object that points to your project XAML resource (compiled BAML, actually), and use the Application.LoadComponent() static method to load and create the root node of the XAML. If you store your DataTemplate in a ResourceDictionary, the code might look something like this:
public RootControl() {
 InitializeComponent();
 Uri uri = new Uri("MyAssembly;component/Templates.xaml", System.UriKind.Relative);
 Resources.MergedDictionaries.Add((ResourceDictionary) Application.LoadComponent(uri);
 
 // ... continue initialization
}
Take a look at the MSDN Uri class definition for details as to why this syntax works. The above code is written for an assembly called "MyAssembly.dll", and with a XAML file called Templates.xaml in the root of the project. If you place your loose XAML files in subfolders, add the path after "component" in the Uri. "component" is really just the root of your project.
MergedDictionaries is a handy way of importing and aggregating resources from different definitions into a single Resources object. By loading the XAML into the root component's merged dictionary, you are indirectly registering the DataTemplate into the current logical scope, meaning it will be applied to your instantiated data.
A note concerning Merged Dictionaries and performance. If you have many resources and they are merged into a control that instantiated many times over, be aware that each Merged Dictionary is created once per component - you may want to look into ways of statically organizing your resources. I'll probably be looking at this on my side and will share any advice concerning this in future posts.
Of course, if your root class has a XAML definition, then go ahead and use this simpler notation:
<RootControl x:Class="UserControl"
 xmlns="..."
 xmlns:x="..." >
<RootControl.Resources>
 <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
       <ResourceDictionary Source="Templates.xaml"/>
    </ResourceDictionary.MergedDictionaries>
 </ResourceDictionary>
 </RootControl.Resources>
</RootControl>
And that's that. Hopefully this post manages not only to convey how to load templates via code, but also provides a bit of insight into how WPF does things under the hood.

Read more...

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Back to TOP