Display HwndHost Inside ToolTip/ContextMenu

| 5 comments

This post is a further elaboration to my reply to this MSDN WPF forum thread.

Before digging into the details of how to solve this issue, let's start with some background information on ToolTip/ContextMenu and HwndHost.

In WPF, ToolTip/ContextMenu is hosted inside a Popup, Popup is essentially a hwnd with WS_POPUP window style. By default, the Popup created by ToolTip and ContextMenu services will have AllowsTransparency property set to true to enable layered windows on it. WPF uses application managed layered windows which is incompatible with the win32/GDI rendering model, which means that application managed layered window doesn't support child hwnd with WS_CHILD window style. So you want to display hwnd based content (through HwndHost) inside the a ToolTip/ContextMenu, you need to disable layered windows.

The caveat here is that the implementation of ToolTip and ContextMenu has hardcoded the AllowsTransparency property value when creating Popup, and it seems that this will not change at least in the next version of WPF. I think it might be common scenario to display content coming from other pre-WPF presentation technologies such as win32 controls, MFC/ActiveX controls or Windows Forms controls etc simply because you already have a control at hand,and it has already implemented all the functionalities you want. There are some known issues with hwnd interop in particular the airspace issue but as long as you don't overlap the hwnd content with WPF content, things should work properly at least visually.

The solution I posted in that WPF forum thread requires subclassing from ToolTip, and override the OnTemplateChanged protected method to wire up the code to set the Popup.AllowsTransparency at the right time before the internal implementation of ToolTip creates it for you which will be too late to set that property(setting Popup.AllowsTransparency to false after the ToolTip/ContextMenu is displayed doesn't take effect immediately, you need to hide the popup and then display it again to get this work). The ideal solution is that I could wire up those logic through the well-known WPF pattern - attached behavior pattern. So I could simply write something like the following, and things start to work for both ToolTip and ContextMenu without separate subclassing:

<StackPanel>
  <
Button Content="ContextMenu Demo">
    <
Button.ContextMenu>
      <
ContextMenu cc:PopupBehavior.AllowsTransparency="False">
        <
WebBrowser Width="300" Height="200" Source="http://www.live.com" />
      </
ContextMenu>
    </
Button.ContextMenu>
  </
Button>
  <
Button Content="ToolTip Demo">
    <
Button.ToolTip>
      <
ToolTip cc:PopupBehavior.AllowsTransparency="False">
        <
WebBrowser Width="300" Height="200" Source="http://www.live.com" />
      </
ToolTip>
    </
Button.ToolTip>
  </
Button>
</
StackPanel>

Here is the complete implementation of PopupBehavior:

using System;
using System.Security;
using System.ComponentModel;

using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace Sheva.Windows.Controls
{
    /// <summary>
    ///
Extends Popup control with added behaviors.
  
/// </summary>
  
public class PopupBehavior
  
{
        public static readonly DependencyProperty AllowsTransparencyProperty =
            DependencyProperty.RegisterAttached(
            "AllowsTransparency",
            typeof(Boolean),
            typeof(PopupBehavior),
            new FrameworkPropertyMetadata(
                true,
                new PropertyChangedCallback(OnAllowsTransparencyChanged),
                new CoerceValueCallback(CoerceAllowsTransparency)));


        public static Boolean GetAllowsTransparency(Control element)
        {
            CheckElementType(element);
            return (Boolean)element.GetValue(AllowsTransparencyProperty);
        }

        public static void SetAllowsTransparency(Control element, Boolean value)
        {
            CheckElementType(element);
            element.SetValue(AllowsTransparencyProperty, value);
        }

        private static Object CoerceAllowsTransparency(DependencyObject element, object baseValue)
        {
            //WPF will force the Popup into WS_CHILD window when running under partial trust, layered windows
            //is only supported for top level windows, so it doesn't make any sense to set the AllowsTransparency to true
            //when running under partial trust.
          
return IsRunningUnderFullTrust() ? baseValue : false;
        }

        private static Boolean IsRunningUnderFullTrust()
        {
            Boolean isRunningUnderFullTrust = true;
            try
          
{
                NamedPermissionSet permissionSet = newNamedPermissionSet("FullTrust");
                permissionSet.Demand();
            }
            catch(SecurityException)
            {
                isRunningUnderFullTrust = false;
            }

            return isRunningUnderFullTrust;
        }

        private static void OnAllowsTransparencyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Control element = (Control)sender;
            CheckElementType(element);

            if(element.IsLoaded)
            {
                //Find the Popup logical element root.
              
Popup popup = GetPopupFromVisualChild(element);
                if(popup != null) popup.SetValue(Popup.AllowsTransparencyProperty, e.NewValue);
            }
            else
          
{
                var templateDescriptor = DependencyPropertyDescriptor.FromProperty(Control.TemplateProperty, element.GetType());

                EventHandler handler = null;
                handler = (obj, args) =>
               {
                   //Not clear why the BeginInvoke call is needed here, but this could effectively
                   //workaround cyclic reference exception when evaluating ToolTip/ContextMenu's Style property.
                 
element.Dispatcher.BeginInvoke(DispatcherPriority.Send, newAction(delegate
                 
{
                       SetAllowsTransparencyInternal(element, e.NewValue);
                   }));

                   //Clear event handler to avoid resource leak.
                 
templateDescriptor.RemoveValueChanged(element, handler);
               };

                templateDescriptor.AddValueChanged(element, handler);
            }
        }

        private static void CheckElementType(Control element)
        {
            if(!(element is ToolTip || element is ContextMenu))
            {
                throw new NotSupportedException("AllowsTransparency attached property can only be applied to ToolTip or ContextMenu");
            }
        }

        private static void SetAllowsTransparencyInternal(Control element, Object value)
        {
            ToolTip tooTip = element as ToolTip;
            ContextMenu contextMenu = element as ContextMenu;

            // Set the IsOpen property to true to let the ToolTip/ContextMenu create Popup instance early, since
            // we are only interesting in Popup.AllowsTransparency property rather than
            // opening the ToolTip/ContextMenu, set its Visibility to Collapsed.
          
element.Visibility = Visibility.Collapsed;
            if(tooTip != null)
            {
                tooTip.IsOpen = true;
            }
            else if(contextMenu != null)
            {
                contextMenu.IsOpen = true;
            }

            //Find the Popup logical element root.
          
Popup popup = GetPopupFromVisualChild(element);
            if(popup != null) popup.SetValue(Popup.AllowsTransparencyProperty, value);

            //Set properties back to what it is initially.
          
if(tooTip != null)
            {
                tooTip.ClearValue(ToolTip.IsOpenProperty);
            }
            else if(contextMenu != null)
            {
                contextMenu.ClearValue(ToolTip.IsOpenProperty);
            }
            element.ClearValue(FrameworkElement.VisibilityProperty);
        }

        private static Popup GetPopupFromVisualChild(Visual child)
        {
            Visual parent = child;
            FrameworkElement visualRoot = null;

            //Traverse the visual tree up to find the PopupRoot instance.
          
while(parent != null)
            {
                visualRoot = parent as FrameworkElement;
                parent = VisualTreeHelper.GetParent(parent) as Visual;
            }

            Popup popup = null;

            // Examine the PopupRoot's logical parent to get the Popup instance.
            // This might break in the future since it relies on the internal implementation of Popup's element tree.
          
if(visualRoot != null)
            {
                popup = visualRoot.Parent as Popup;
            }

            return popup;
        }
    }
}

I have fully commented the code so it might be a little bit more straightforward to read. All in All, the implementation is a little bit like a hack, and might be broken in the future version of WPF as I commented above:)
Here is the complete VS project: HwndHostInPopupDemo.zip

When Selector.IsSynchronizedWithCurrentItem will be true?

| 2 comments

This looks like an obvious question, you when set it to true either through XAML or code, then the Selector's (such as ListBox and ComboBox) selection operation will drive the setting of the current item within CollectionView which presents the data bound source collection, so when you want to synchronize current item with the selected item, you could write something like the following XAML snippet:

<
Pagexmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <
Page.Resources>
    <
x:Arrayx:Key="data" Type="{x:Type sys:String}">
      <
sys:String>Paviel Dedved</sys:String>
      <
sys:String>Andriy Shevchenko</sys:String>
      <
sys:String>Paolo Maldini</sys:String>
      <
sys:String>Robert Baggio</sys:String>
      <
sys:String>Alessandro Del Piero</sys:String>
    </
x:Array>
  </
Page.Resources>
  <
StackPanel DataContext="{StaticResource data}">
    <
ListBox ItemsSource="{Binding}" Margin="5" IsSynchronizedWithCurrentItem="True"/>
    <
ComboBox ItemsSource="{Binding}" Margin="5" IsSynchronizedWithCurrentItem="True"/>
    <
TextBlock>CurrentItem: <TextBlock Text="{Binding /}"/>
    </
TextBlock>
  </
StackPanel>
</
Page>

From the above code, the ListBox and ComboBox is data bound to the same source collection, but for each ItemsSource binding, a unique CollectionView is generated, so that both ListBox and ComboBox can make independent selection without affecting each other, this is what most developers expect. So if you want both ListBox and ComboBox to drive the currency, you need to explicitly set the IsSynchronizedWithCurrentItem property to true, this is pretty obvious and straightforward, isn't it?

If you think this is an obvious thing to do, then I have another XAMLPad ready example which might confuse you:

<
Pagexmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <
Page.Resources>
    <
x:Arrayx:Key="data" Type="{x:Type sys:String}">
      <
sys:String>Paviel Dedved</sys:String>
      <
sys:String>Andriy Shevchenko</sys:String>
      <
sys:String>Paolo Maldini</sys:String>
      <
sys:String>Robert Baggio</sys:String>
      <
sys:String>Alessandro Del Piero</sys:String>
    </
x:Array>
    <
CollectionViewSource x:Key="src" Source="{StaticResource data}"/>
  </
Page.Resources>
  <
StackPanel DataContext="{StaticResource src}">
    <
ListBox ItemsSource="{Binding}" Margin="5"/>
    <
ComboBox ItemsSource="{Binding}" Margin="5"/>
    <
TextBlock>CurrentItem: <TextBlock Text="{Binding /}"/>
    </
TextBlock>
  </
StackPanel>
</
Page>

If you run above XAML snippet in XAMLPad, you will find that both ListBox and ComBox can drive the currency as if the IsSynchronizedWithCurrentItem property is set to true. so what happens?

If you use reflector to example the source code of the Selector, if you will the SetSynchronizationWithCurrentItem() method implementation as follows:

private void SetSynchronizationWithCurrentItem()
{
    bool? isSynchronizedWithCurrentItem = IsSynchronizedWithCurrentItem;
    bool oldSync = IsSynchronizedWithCurrentItemPrivate;
    bool newSync;

    if (isSynchronizedWithCurrentItem.HasValue)
    {
        // if there's a value, use it
       
newSync = isSynchronizedWithCurrentItem.Value;
    }
    else
   
{
        // when the value is null, synchronize if selection mode is Single
        // and there's a non-default view.
       
SelectionMode mode = (SelectionMode)GetValue(ListBox.SelectionModeProperty);
        newSync = (mode == SelectionMode.Single) &&
        !CollectionViewSource.IsDefaultView(Items.CollectionView);
    }

    IsSynchronizedWithCurrentItemPrivate = newSync;

    if (!oldSync && newSync)
    {
        SetSelectedToCurrent();
    }
}

From the bolded line of code, it seems that this is an intentional behaviour, which means that if the SelectionMode of Selector is Single, and the CollectionView data bound to the Selector is not the implicit, default View generated by WPF's data binding engine, Selector will drive the currency. This might not make sense to you, but after the following explanation, I hope it finally makes sense to you.

There are two aspects for this issue, the first is multi selection, and the second is non-default view.

First, it's no brainer that when the Selector is in Multiple SelectionMode, WPF can not take on current synchronization, because there is no such concept of "multi-current items" from the perspective of each ICollectionView implementation(CollectionView for IEnumerable, ListCollectionView for IList and BindingListCollectionView for IBindingList etc), you might think that WPF can choose one item from the selected items as the current item, but it's hard to figure out which one is the best candidate for current item, because this decision usually varies tremendously in different scenarios, and it's nearly impossible for a general purpose framework like WPF to make a good decision for you.

Second, WPF drives currency if you are using the non-default explicit CollectionView, this usually is achieved by declaring the underlying data to be CollectionViewSource, because when you use CollectionViewSource which is a XAML friendly version of CollectionView, WPF assumes that you are mostly likely wanting to enable master/detail binding, and it's obvious that you need the currency synchronization service provided by Selector. So WPF thinks that it's a good default and correct behaviour to implicitly turn on currency synchronization for you.

Knowing that this is the heuristics WPF makes on how you are going to use the data, and it might cause some incorrect behaviour as reported in this WPF MSDN forum thread, so it might worth a blog entry to point this out:)

BTW, for any one who thinks that the {Binding /} syntax is alien to them, you could refer to this Ian Griffith's excellent blog post for explanation.

The Power of Shader - Part One

| 1 comments

.NET Framework 3.5 SP1 Beta1 has been released, this release is not simply a service pack release as we've known for many years of what  SP actually means. It seems that Microsoft has changed its strategy, and start to include new features in SP release.

One of the most exciting feature of this release is a new hardware accelerated, pixel shader based custom effect architecture which drives the software, WIC based bitmap effect architecture into obsolete. This new architecture has tackle many of the performance problems inherent with previous stale architecture. On one hand, the new custom effect will run in composition thread rather than UI thread, which means that it will not tie up the UI thread as the previous effect does, on the other hand, it will be hardware accelerated if your GPU supports pixel shader 2.0 or above. If you don't have decent GPU, the effect will be emulated using software, RenderTargetBitmap is a special case, if any visual which has effect applied to it needs to be rasterized into the RenderTargetBitmap, it will go through software rendering path.

If you have read the blog series written by Greg Schechter about the new shader effect feature, you could have been familiar with how to create simple effects. But those shader effect expects you to pass in the pre-compiled HLSL bytecode, which really requires you to use the shader compiler (fxc.exe) which is shipped with the DirectX SDK to compile the shader first, then pass it to the ShaderEffect derivative's constructor. How about if I want to directly pass in the source shader string, and have it get compiled and executed at runtime, this is called online compilation as compared with offline compilation with fxc.exe tool. Fortunately, I could use the Microsoft.DirectX.Direct3D.ShaderLoader class which is part of the managed DirectX API which can do exactly what I want, Here is the ShaderEffect implementation which supports online compilation:

public class SourceShaderEffect : ShaderEffect
{
    // The custom effect expects pixel shader 2.0 support.
    public static readonly String PixelShaderProfile = "ps_2_0";

    public static readonly ShaderFlags ShaderFlags = ShaderFlags.None;

    // We use "main" as the default function name for the shader.
    public static readonly String DefaultFunctionName = "main";

    /// <summary>
    /// Constructs a new SourceShaderEffect instance.
    /// </summary>
    /// <param name="shaderFilePath">path to the source shader file</param>
    /// <param name="functionName">shader entry function name</param>
    public SourceShaderEffect(String shaderFilePath, String functionName)
    {
        GraphicsStream stream = ShaderHelper.TryThrowCriticalException(() =>
        {
            return ShaderLoader.CompileShaderFromFile(
                shaderFilePath,
                functionName,
                null,
                PixelShaderProfile,
                ShaderFlags);
        });

        if (null != stream)
        {
            base.PixelShader = new PixelShader();
            base.PixelShader.SetStreamSource(stream);
        }
    }

    /// <summary>
    /// Constructs a new SourceShaderEffect instance.
    /// </summary>
    /// <param name="shaderStream">stream which contains the shader source code.</param>
    /// <param name="functionName">shader entry function name</param>
    public SourceShaderEffect(Stream shaderStream, String functionName)
    {
        GraphicsStream stream = ShaderHelper.TryThrowCriticalException(() =>
       {
           return ShaderLoader.CompileShaderFromStream(
               shaderStream,
               functionName,
               null,
               PixelShaderProfile,
               ShaderFlags);
       });

        if (stream != null)
        {
            base.PixelShader = new PixelShader();
            base.PixelShader.SetStreamSource(stream);
        }
    }

    /// <summary>
    /// Constructs a new SourceShaderEffect instance with default shader entry function name.
    /// </summary>
    /// <param name="shaderFilePath">path to the source shader file</param>
    public SourceShaderEffect(String shaderFilePath) : this(shaderFilePath, DefaultFunctionName) { }

    /// <summary>
    /// Constructs a new SourceShaderEffect instance with default shader entry function name.
    /// </summary>
    /// <param name="shaderStream">stream which contains the shader source code.</param>
    public SourceShaderEffect(Stream shaderStream) : this(shaderStream, DefaultFunctionName) { }
}

 

There is no fancy stuff in this code, with the above code, you could simply pass a file path or stream to the shader source code, and you are done with it. Let's create a simple effect to see if it actually works, the following is a Sepia shader which I learnt from this nice article:

sampler2D s0 : register(s0);
float4 main(float2 tex : TEXCOORD0) : COLOR
{
    float4 color = tex2D(s0, tex);
    float value = color[0] * 0.299f + color[1] * 0.587f + color[2] * 0.114f;
    return tex2D(s0, value);
}

Let's save it into a file called Sepia.fx, and add it as a resource file into the WPF project you create from visual studio. In XAML, you could place an Image element, and at the code behind, you could write something like the following:

image.Effect = CreateSourceShaderEffect("Sepia");


public static ShaderEffect CreateSourceShaderEffect(String shaderLocation)
{
    ShaderEffect effect = null;
    shaderLocation = "pack://application:,,,/Shaders/" + shaderLocation + ".fx";
    Stream shaderStream = Application.GetResourceStream(new Uri(shaderLocation, UriKind.Absolute)).Stream;
    if (null != shaderStream)
    {
        effect = new SourceShaderEffect(shaderStream);
    }

    return effect;
}

 

Then, it seems that you've got everything ready to run, but actually you don't, if you are running under 64 bit Windows, you need to set the visual studio build system to target X86 architecture instead, otherwise you will get a BadImageFormatException. This means that to enable online compilation, your Application should be 32 bit, and it will be emulated when running under 64 bit Windows through WOW64 layer, which might not be what you expect. so if you are targeting 64 bit Windows, and you want your WPF application to be 64 bit, this technique is not the way to go, otherwise, it could be an option for you.

The following is a full sample code with another two simple shader effects such as Invert, and Grayscale. On the next installment, I will try to take adventure on shader effects with input parameters and with multi-sampler blending when I learnt how to do them:)

Attachment:ShaderEffectDemo.zip

Applicatons = Markup + Code

| 1 comments

I was asked by one of Chinese leading ComSci book publishers to write a book review on Charles Petzold's classical WPF book Applications = Markup + Code, because they've just finished with translating this awesome book into Chinese. Charles is always one of my most respectable .NET gurus, and here is my humble attempt at commentting on his book:

Windows Presentation Foundation hits the Windows programming community quite tremendously from the very beginning of its CTP release not only because it's a much better and superior technology than the stale GDI/USER based UI Framework, but also because it brings in a new programming paradigm that most Windows programmers might have never thought of, that is Applications = Markup + Code.

Windows Presentation Foundation is Microsoft's first attempt at unifying the programming model both for Windows desktop and the Web going forward (with the introduction of Silverlight, you can employ the same programming concept and techniques to author Rich Internet Applications). Windows Presentation Foundation also enables a new workflow between developers and designers, with Windows Presentation Foundation, designers has become an integral part of the whole software development process, and they will have a vital say over the final appearance of the whole UI, because they are trained for this, and specialized at doing this. This can free the developers from concerning about something they are not good at, such as how to adjust the colour contrast to make the Button looks more esthetically pleasing.

Windows Presentation Foundation also integrates text, imaging, graphics (both 2D and 3D), animations, audio/video, documents, printing, and resources management APIs into a single framework, those powerful APIs and toolsets really enable developers to build rich visualization applications. The ability to seamlessly incorporate 2D content over 3D scenes and vice versa is simply stunning which gives possibility to write Northface Demo type of applications.

Charles Petzold brings in his years of Windows programming experiences to provide us with a hitchhikers' guide around Windows Presentation Foundation first from the perspective of code, then XAML (Extension Application Markup Language), which might be the ultimate UI definition language for Windows moving forward. From Chapter 1 to Chapter 17, Charles first introduces us the basic WPF controls and how they differ from traditional win32/Windows Forms counterparts, he also teaches us probably the most important core concepts of WPF such as Dependency Properties and Routed Events which is a little bit different from what we've known about properties and events in C#. He also gives us a de tour on how to write a custom layout panel to layout elements/controls in a predefined manner which is pretty useful when you want to roll up your own data presentation controls. In the unique Chapter 18, Charles aggregates what we've learnt from the previous chapters to tell us how to write a full-blown WPF application such as Notepad. From Chapter 19 to Chapter 31, the amazing XAML tour starts. Again in those Chapters, Charles still focus on the basic building block of WPF such as navigation, geometrical transformation, data binding, control templates and data templates etc, but this time, from the XAML perspective, he tells us how to declaratively specify WPF constructs, and how they relate to their code representations, which is very important, this can help developers to better understand XAML, what it can and cannot do.

Charles' book just covers hoards of WPF contents and concept which I cannot name it all, but suffice it to say that I find the book Applications = Markup + Code quite complete, informative and interesting to read. I think this book should be put onto every serious WPF developer's bookshelves, what you think?

WPF, Terminal Services & Bitmap Remoting

| 1 comments

Everybody who has been playing around with WPF for a reasonable period of time might have known that WPF Application Processing is actually split up into two threads, they are UI thread which runs the dispatcher loop, and processes any GUI, keyboard/mouse/ink input, animation, layout and user initiated messages/events, and there is a hidden unmanaged background thread which is responsible for composing the graphical content (both in hardware or software if fallback is needed), and presenting it to frame buffer for display.

The whole architecture of WPF is built around this two threads model, and it has some of the benefits as articulated by Chris Anderson in the two-year long Channel video. One of the benefits Chris mentioned is that with the two threads model, in terminal services scenario, we can have the UI thread running in the TS server, and have the composition thread (or render thread in other nomenclature) running at the TS client console. And the communication between the two threads are handed over to the TS/RDP protocol. This can enable one interesting scenario called primitive remoting or vector remoting. And since UI thread is running at the TS server side, and it maintains the visual tree and the composition is at the TS client side, so in order to keep the client screen up to date, the UI thread will send the edits to the composition tree over the TS/RDP protocol in a highly compressed manner, this not only saves the network bandwidth, because only the edits need to be remoted, but also speeds up the client processing. This type of server/client communication also holds true in the standalone WPF application, the difference is that those two threads are running at the same Win32 process, and the inter-thread communication mechanism is used instead of the TS/RDP wire. To enable primitive remoting, both the TS server and TS client should run under Windows Vista and with desktop composition is enabled, this requirement tremendously narrows down the scenario in which the primitive remoting could be leveraged.

The upcoming .NET Framework 3.5 SP1 release would change all of this, in particular, bitmap remoting with sub region update support will always be used even if the TS server and the TS client are equipped to support primitive remoting, primitive remoting can be as good or bad as bitmap remoting, and the scenario in which primitive remoting is enabled is quite rare, because most existing Windows servers such as Windows 2000 or Windows 2003 server families don't support primitive remoting. So for any developer who wants your WPF applications to run reasonably well under TS scenario and running under TS is an important scenario for your applications, you need to take implication of bitmap remoting into consideration beforehand, there are a couple of ways from which you can improve the performance of your WPF application in TS scenario:

  • Considering using as little animations as possible in your application, and if animations are indispensable, you could try reducing the DesiredFrameRate (The default value is 6O FPS) of each animations you need to use, usually 25~30 FPS should be enough, and if you don't need high fidelity animation experience, you can use a even lower frame rate.
  • Considering using solid color brushes instead of gradient or tile brushes.
  • Try reducing the number of "hidden redraws" your application needs to perform, "hidden redraws" will be overlaid by its most foreground redraws, but they will still be remoted which waste network bandwidth. You can visualize the "hidden redraws" using the Perforator (part of WPF Performance Suite) with "Show dirty-regions update overlay" CheckBox checked.

How to Reference Named Elements Within CellTemplate?

| 0 comments

Getting reference to the named elements within data template is a commonly requested feature of WPF. In the current version of WPF, there is no intuitive and straightforward way to do it, you need to either traverse the visual tree to compare the Name property of each FrameworkElements within the tree, or alternatively you can first off grab the reference to the ContentPresenter within the ControlTemplate, and call DataTemplate.FindName() passing in the ContentPresenter reference as the "templatedParent" argument. Accessing named elements within CellTemplate complicates the things a bit since each Cell will have different instantiation of CellTemplate, the following helper class gives a possible solution to this problem (I also posted it in this WPF MSDN forum thread):

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace Sheva.Windows.Component
{
    public static class ListViewHelper
  
{
        /// <summary>
        ///
Finds an element that has the provided identifier name within the specified cell template identified by the cellColumn and cellRow
      
/// </summary>
        /// <param name="listView">
the referenced ListView control</param>
        /// <param name="cellColumn">
the index of column from which the CellTemplate will be retrieved</param>
        /// <param name="cellRow">
the index of the row from which the specified ListViewItem will be retrieved</param>
        /// <param name="name">
The name of the requested element.</param>
        /// <returns>
The requested element. This can be null reference if no matching element was found.</returns>
      
public static FrameworkElement FindNameFromCellTemplate(ListView listView, Int32 cellColumn, Int32 cellRow, Stringname)
        {
            if(listView == null)
            {
                throw newArgumentNullException("listView");
            }

            if(!listView.IsLoaded)
            {
                throw new InvalidOperationException("ListView is not yet loaded");
            }

            if (cellRow >= listView.Items.Count || cellRow < 0)
            {
                throw new ArgumentOutOfRangeException("row");
            }

            GridView gridView = listView.View as GridView;
            if (gridView == null)
            {
                return null;
            }

            if (cellColumn >= gridView.Columns.Count || cellColumn < 0)
            {
                throw new ArgumentOutOfRangeException("column");
            }

            ListViewItem item = listView.ItemContainerGenerator.ContainerFromItem(listView.Items[cellRow]) as ListViewItem;
            if (item != null)
            {
                if (!item.IsLoaded)
                {
                    item.ApplyTemplate();
                }
                GridViewRowPresenter rowPresenter = GetFrameworkElementByName<GridViewRowPresenter>(item);

                if(rowPresenter != null)
                {
                    ContentPresenter templatedParent = VisualTreeHelper.GetChild(rowPresenter, cellColumn) as ContentPresenter;
                    DataTemplate dataTemplate = gridView.Columns[cellColumn].CellTemplate;
                    if(dataTemplate != null && templatedParent != null)
                    {
                        return dataTemplate.FindName(name, templatedParent) as FrameworkElement;
                    }
                }
            }

            return null;
        }

        private static T GetFrameworkElementByName<T>(FrameworkElement referenceElement) where T : FrameworkElement
      
{
            FrameworkElementchild = null;
            for(Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceElement); i++)
            {
                child = VisualTreeHelper.GetChild(referenceElement, i) as FrameworkElement;
                if(child != null && child.GetType() == typeof(T))
                {
                    break;
                }
                else if(child != null)
                {
                    child = GetFrameworkElementByName<T>(child);
                    if(child != null && child.GetType() == typeof(T))
                    {
                        break;
                    }
                }
            }
            returnchild asT;
        }
    }
}

This actually requires a bit of coding, hopefully future version of WPF in particular the ListView control could has a much better content model to make it more flexible and extensible than it is right now.