WPF Discussion 090922
Raw, unedited, insightful and deep content from our internal WPF discussion…
Subject: Any chance of INotifyCollectionChanged moving to the core .NET libraries?
The System.Collections.Specialized.INotifyCollectionChanged interface is defined in WindowsBase.dll (primarily a WPF assembly) but my customer believes it should be pushed down into the core BCL so that other project types can benefit from it without requiring a reference to WPF/WindowsBase.
Is this planned for 4.0 or later?
Answer:
INotifyCollectionChanged, ObservableCollection<T>, and ReadOnlyObservableCollection<T> have been type forwarded into System.dll for .NET 4.
Subject: Why TextRange.Load(MemoryStream, DataFormats.Xaml) can not work?
I am trying to load a flowdocument from a Xaml file using TextRange.Load(MemoryStream, DataFormats.Xaml) method, but the following code does not work:
FlowDocument f = new FlowDocument();
TextRange range = new TextRange(f.ContentStart, f.ContentEnd);
StreamReader sr = new StreamReader(@"TextFile1.xaml");
string aa = sr.ReadToEnd();
MemoryStream ms = new MemoryStream(System.Text.Encoding.Default.GetBytes(aa));
range.Load(ms, System.Windows.DataFormats.Xaml);
I know if I use XamlReader.Load method will do the trick, but I don’t understand why the above code can’t work. Is this a bug or I am missing something?
Answer:
DataFormats.Xaml (and XamlPackage) are misleading – when consumed by TextRange.Load they only work on a subset of xaml generated by TextRange.Save. The TextRange.Save/Load api is intended for editing scenarios where you need to persist arbitrary selections that may cross element boundaries (e.g., you need to save half of a Paragraph).
For your scenario, where you’re loading loose xaml from a file, XamlReader is the way to go.
Subject: What is "Unlabeled time" in Visual Proiler that is part of Performance Profiling Tools for WPF?
Answer:
Any CPU time that we aren’t able to attribute to a specific WPF operation goes in the unlabeled bucket. This includes time spent in CLR operations such as garbage collection and time spent in the application’s own code.
Subject: Accessibility issue with WPF DataGrid and NewItemPlaceholder
We’ve run into an accessibility issue with the WPF DataGrid concerning the NewItemPlaceholder. Specifically, we’re re-templating the placeholder control in order to add a “real” click-here-to-add-a-new-item button. However, none of the UI elements in the new template are available to accessibility-based automation (i.e. the button does not show up in UISpy or AccExplorer). The template is set during the DataGrid LoadingRow event and looks like this:
<ControlTemplate x:Key="SafeControlNewRowControlTemplate" TargetType="{x:Type DataGridRow}">
<SelectiveScrollingGrid>
<Button Content="Click here to add a new item." Margin="5,5,0,0" x:Uid="AssemblyDialogWindow_SafeControlAddNewItem" Click="OnSafeControlNewRowButtonClicked"/>
</SelectiveScrollingGrid>
</ControlTemplate>
Answer:
Yeah the AutomationPeers for all of the DataGrid components are structured around rows and cells. In your scenario you are retemplating a row (NewItemPlaceHolder row) so it does not have cells. Unfortunately the AutomationPeers do not recognize this. So you will in fact need to jump through some hoops to enable this scenario.
- Subclass DataGridRowAutomationPeer and override GetChildrenCore to special case NewItemPlaceHolder row and return the visual children instead of the cells.
- Subclass DataGridRow and override OnCreateAutomationPeer to return the subclassed DataGridRowAutomationPeer.
- Subclass DataGrid and override GetContainerForItemOverride to return the subclassed DataGridRow.
Subject: Adding ContextMenu to DataGrid header
I am using WPF 4.0 DataGrid and want to add context menu only to the header. The way that I found to do is to add a ContextMenu setter property to a style and assign the style to the DataGrid.ColumnHeaderStyle.
Answer: This is the right way of setting the context menu on DataGridColumnHeader (either using an implicit style for DataGridColumnHeader or setting it explicitly using ColumnHeaderStyle property).
But this puts restriction that a style needs to be added to the ColumnHeader. Performing SetValue on “DataGridColumnHeader.ContextMenuProperty” somehow sets it for the entire grid. The context menu should only be for the header.
Answer: This won’t work. When one uses ‘DataGridColumnHeader.ContextMenu’ property, note that one is using the property which internally happens to be the same for DataGrid too (because ContextMenu is defined on FrameworkElement and all controls share the same property definition). Hence that would end up setting the value of DataGrid itself.
Is there any way to add context menu only to the header w/o having to set ColumnHeaderStyle?
Answer: Use implicit style for DataGridColumnHeader. But honestly I don’t see any difference from using ColumnHeaderStyle.
Subject: Adding HierarchicalDataTemplate via UI?
How can I add a HierarchicalDataTemplate for Silverlight 3 via the Blend 3 UI (without typing in the class in XAML)?
Answer:
Steps:
1. Create a new sample data
2. Click on the triangle of “add simple property”, select “convert to Hierarchical Collection”
3. Drag the converted Hierarchical Collection to artboard
View the xaml, notice the Blend generated HierarchicalDataTemplate is bound to the generated tree view.
Here is a more complete TreeView editing experience write-up:
https://shawnoster.com/Blog/Silverlight-TreeView-Connecting-Lines-And-Blend-3-Support-for-HierarchicalDataTemplates
Subject: debugging an unmanaged exception in WPF app.
tried to debug my application I saw the following message “The debugger does not support debugging managed and native code at the same time on this platform.”
How could I enable only native code debugger without managed one?
Answer:
There may be other ways, but this should work.
Right-Click on the solution, select “Add Existing Project” and select the compiled exe.
Set the exe project as the startup project.
Right-Click, go to Properties and set “Debugger Type” to “Native Only”
Subject: API that can determine whether a keystroke yields printable characters or not
I have a KeyDown event and System.Windows.Input.KeyEventArgs event arg e.
Is there any API that I can use to determine whether this e.Key is printable or not? Or is there any API I can get the character of this keystroke?
Answer:
Generally, no. KeyDown to text conversion is pretty stateful, and you don’t have access to this state. Most of it is maintained by the OS.
Subject: XBAP and multi touch in Windows7
Will all multi touch features in WPF 4 be available when running on Windows 7 as XBAPs as well?
Answer:
Yes, manipulation and touch events are available in PT. However you cannot implement your own touch device.
Subject: X:Name and Name property
I have a quick question on why do we have Name for some of the Classes and have to use x:Name for the classes related to Animation/Timelines. Why is this difference in the framework and no uniformity?
Answer:
XAML uses [RuntimeNameProperty(“somePropName”)] on classes to signify when a property is the “Name” property (and thus aliased with x:Name).
XAML treats the two interchangeably when a type does have a RutimeName declared.
If a tag has both, that is an error.
Reasons for where we ended up:
· We wanted WPF to not have to require 2 namespaces to have a Named object.
· We didn’t want to hard code all “Name” properties as the Name.
Subject: WPF colour depth rendering support
Hi all,
I'm working on an application that displays DICOM images, the spec allows for images to have greater than 8 bits per channel which most if not all of my test data does have and is very common in medical images. I read on https://blogs.msdn.com/dwayneneed/archive/2008/06/20/implementing-a-custom-bitmapsource.aspx that "The WPF rasterizer only natively renders bitmaps in Bgr32 and PBgra32 formats" (In the 'WIC in WPF' section, 5th paragraph), is there any way to have a WPF application render an image in PixelFormats.Prgba64 or PixelFormats.Gray16 (or an equivalent)?
Thanks,
Answer:
No. As Dwayne’s blog notes, the WPF rendering pipeline operates in 32-bit only, so all images are format converted to that before being processed.
Subject: Workaround for IsDeferredScrollingEnabled bug
When using a ComboBox inside of a ScrollViewer with IsDeferredScrollingEnabled=true scrolling in the ComboBox does not work correctly.
Answer:
You’ve certainly hit a bug and we are recording one for this scenario. As for a workaround, you can set IsDeferredScrollingEnabled to true for the ComboBox as well to get all the scrollviewers to work correctly. Like this.
<StackPanel.Resources>
<Style TargetType="ComboBox">
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="true" />
</Style>
</StackPanel.Resources>
Subject: WindowStyle.None + ResizeMode.CanResize vs. NoResize
I’m trying to recreate a window like the volume window, where there’s minimal chrome and cannot be resized.
WindowStyle.None renders a window without a title bar. ResizeMode.NoResize will make a window not resize (surprise, surprise). Unfortunately, when you use them both together, there is no window chrome at all. I’ve tried setting the min/max height/width, which works, but I still get the resize mouse icon when I hover over the window border. Is it possible to render a minimal chrome without the resize icon?
Answer:
I think you should be able to use what you have and p/invoke to set the Window's native style to include WS_BORDER.
There isn't a combination in WPF's Window that supports what you're trying to express.
Subject: Window chrome size
Is there a way to get the height of the title bar and width of little border on the left in a window. I’m trying to create an overlay window via databinding (would use popup, but it doesn’t seem to respect bindings like Window does) so I need to add in the chrome size to find the global position of the window’s client area. Or maybe there is an easier way?
Answer:
You might try Visual.PointToScreen to see if it does what you want. I think it gives coordinates in actual device pixels, so if you need to position your overlay using WPF's 1/96" units, you'll have to multiply by 96/systemDPI. With some effort, you can get this scale factor from HwndTarget.TransformFromDevice.
Subject: RE: Viewing WPF applications over Citrix
What would be the implications of running WPF over Citrix.
Answer:
All versions of WPF since WPF 3.5 SP1 have remoted (both with Remote Desktop and Terminal Server) using Bitmap Remoting.
Bitmap remoting works as follows:
- The application is rendered on the server using WPF’s software rasterizer
- As the application runs, the server keeps track of which regions of the application’s window are newly dirty and need to be updated
- When a region needs to be updated, the server creates a compressed bitmap of just the dirty region and sends that to the client
- Once the client has drawn that bitmap to the appropriate place on its own window, the client window is up-to-date
Given how this remoting mechanism works, performance can be maximized in several ways:
- Dirty regions should be kept as small as possible so the least amount of data is sent over the wire
- Ambient animations should be turned off.
- For instance, setting a window background to an animating gradient would cause the entire window to be invalidated / redrawn every frame
- The system does not optimize away occluded parts of the application
- For instance, an animation that is completely hidden behind some other opaque element will still cause dirty region invalidation / bitmap generation to occur. Remove these from your application.
- Dirty regions should be created as infrequently as possible
- Turn off as many animations as possible
- For those animations that can’t be eliminated completely, lower the animation framerate using the DesiredFramerate property
- Dirty Region Bitmaps should be as simple as possible to maximize their compression
- Application running over TS should favor solid colors over gradients or other exotic fills (unnecessary images, etc), especially for application pieces that will be redrawn frequently
- Avoid operations that are especially slow when rendered in software
- BitmapEffects / Effects / ShaderEffects, especially blurs and drop shadows with large radii, are quite slow in software
- 3D – the 3D software rasterizer is substantially slower than rendering in hardware
Subject: Spell checker does not pick up the current input language if it changes
If I create an empty application, with:
<TextBox SpellCheck.IsEnabled="True" />
And I enter text in English, all is good. If I delete all my text in that textbox, change my input language to German (for example), and input German words, it will still be spell checking in English. If I restart the app with my input language set to German, it will spell check correctly.
Answer:
It’s by design. TextBox doesn’t track input language (unlike RichTextBox, which will tag every character entered with the current input language). TextBox can’t track the input language of individual characters because it contains nothing but Unicode. So,
1. If TextBox.Language is set, the speller will respect it.
2. If TextBox.Language is unset/default (en-us), the speller uses a heuristic, reading the input language set when spelling is enabled.
Language is an inheritable property, so setting it on any parent element will affect a TextBox. The speller will honor any Language value that is not default -- local, inherited, or styled.
Subject: turn off bitmap effects?
Is there a registry setting to turn off bitmap effects?
Answer:
No there isn’t. But in 4.0 all the *BitmapEffect classes are either no-opd or redirected to their *Effect equivalents (for the case of DropShadow and Blur).
Subject: RadioButton/ToggleButtons with DataBinding
Does anyone have an example of a group of RadioButtons or ToggleButtons working with DataBinding?
We've found it quite difficult to get this working in a straightforward way.
Answer:
Ralph, yes there are known issues about RadioButtons and other Controls setting local values upon user interaction and hence clobbering app set Bindings in .Net 3.5
I've worked around this issue in .NET 3.5 SP1. Here's how I data bind a group of radio buttons to an enum-valued property:
<StackPanel>
<RadioButton Content="New folder"
IsChecked="{Binding Path=PublishTarget,
Converter={StaticResource equalityConverter},
ConverterParameter={x:Static local:PublishTarget.NewServerFolder},
Mode=TwoWay}"
GroupName="1"/>
<RadioButton Content="Existing folder"
IsChecked="{Binding Path=PublishTarget,
Converter={StaticResource equalityConverter},
ConverterParameter={x:Static local:PublishTarget.ExistingServerFolder},
Mode=TwoWay}"
GroupName="2"/>
<RadioButton Content="Local folder"
IsChecked="{Binding Path=PublishTarget,
Converter={StaticResource equalityConverter},
ConverterParameter={x:Static local:PublishTarget.LocalFolder},
Mode=TwoWay}"
GroupName="3"/>
</StackPanel>
Setting each radio button's GroupName to a unique value prevents the bindings from getting clobbered when the user clicks on a radio button. Here I'm relying on the data source to implement INotifyPropertyChanged, which will tell the other radio buttons to update. A similar approach should work for radio buttons in an ItemsControl.