`
v5browser
  • 浏览: 1137279 次
社区版块
存档分类
最新评论

[WPF] How to bind to data when the DataContext is not inherited

 
阅读更多

The DataContext property in WPF is extremely handy, because it is automatically inherited by all children of the element where you assign it; therefore you don’t need to set it again on each element you want to bind. However, in some cases theDataContext is not accessible: it happens for elements that are not part of the visual or logical tree. It can be very difficult then to bind a property on those elements…

Let’s illustrate with a simple example: we want to display a list of products in aDataGrid. In the grid, we want to be able to show or hide the Price column, based on the value of aShowPrice property exposed by the ViewModel. The obvious approach is to bind the Visibility of the column to the ShowPrice property:

1
2
3
<DataGridTextColumnHeader="Price"Binding="{Binding Price}"IsReadOnly="False"
Visibility="{Binding ShowPrice,
Converter={StaticResource visibilityConverter}}"/>

Unfortunately, changing the value of ShowPrice has no effect, and the column is always visible… why? If we look at the Output window in Visual Studio, we notice the following line:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=ShowPrice; DataItem=null; target element is ‘DataGridTextColumn’ (HashCode=32685253); target property is ‘Visibility’ (type ‘Visibility’)

The message is rather cryptic, but the meaning is actually quite simple: WPF doesn’t know which FrameworkElement to use to get the DataContext, because the column doesn’t belong to the visual or logical tree of theDataGrid.

We can try to tweak the binding to get the desired result, for instance by setting the RelativeSource to theDataGrid itself:

1
2
3
4
<DataGridTextColumnHeader="Price"Binding="{Binding Price}"IsReadOnly="False"
Visibility="{Binding DataContext.ShowPrice,
Converter={StaticResource visibilityConverter},
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/>

Or we can add a CheckBox bound to ShowPrice, and try to bind the column visibility to theIsChecked property by specifying the element name:

1
2
3
4
<DataGridTextColumnHeader="Price"Binding="{Binding Price}"IsReadOnly="False"
Visibility="{Binding IsChecked,
Converter={StaticResource visibilityConverter},
ElementName=chkShowPrice}"/>

But none of these workarounds seems to work, we always get the same result…

At this point, it seems that the only viable approach would be to change the column visibility in code-behind, which we usually prefer to avoid when using the MVVM pattern… But I’m not going to give up so soon, at least not while there are other options to consider ;)

The solution to our problem is actually quite simple, and takes advantage of theFreezable class. The primary purpose of this class is to define objects that have a modifiable and a read-only state, but the interesting feature in our case is that Freezable objects can inherit the DataContext even when they’re not in the visual or logical tree. I don’t know the exact mechanism that enables this behavior, but we’re going to take advantage of it to make our binding work…

The idea is to create a class (I called it BindingProxy for reasons that should become obvious very soon) that inheritsFreezable and declares a Data dependency property:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protectedoverride Freezable CreateInstanceCore()
{
return newBindingProxy();
}
#endregion
publicobject Data
{
get { return(object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
publicstatic readonlyDependencyProperty DataProperty =
DependencyProperty.Register("Data",typeof(object),typeof(BindingProxy),new UIPropertyMetadata(null));
}

We can then declare an instance of this class in the resources of the DataGrid, and bind the Data property to the current DataContext:

1
2
3
<DataGrid.Resources>
<local:BindingProxyx:Key="proxy"Data="{Binding}"/>
</DataGrid.Resources>

The last step is to specify this BindingProxy object (easily accessible withStaticResource) as the Source for the binding:

1
2
3
4
<DataGridTextColumnHeader="Price"Binding="{Binding Price}"IsReadOnly="False"
Visibility="{Binding Data.ShowPrice,
Converter={StaticResource visibilityConverter},
Source={StaticResource proxy}}"/>

Note that the binding path has been prefixed with “Data”, since the path is now relative to theBindingProxy object.

The binding now works correctly, and the column is properly shown or hidden based on theShowPrice property.

From: http://www.thomaslevesque.com/tag/datacontext/

分享到:
评论

相关推荐

    WPF Data Binding with LINQ to SQL

    This is the final part of a three-part ...The purpose of this final article is to complete the introduction to LINQ to SQL by showing how to make your LINQ to SQL classes work with WPF data bindings.

    Illustrated WPF (Expert's Voice in .Net)

    * How to bind visual elements to data sources. * How to perform graphics transformations to produce eye–catching displays, and how to use animation to produce pages that are alive with action. * ...

    MVVM Demo for WPF

    Having helped alot of people on the MSDN Forum in the WPF section, I tend to see alot of people who fail to exploit the benefits of DataBinding in WPF, and not enough people are aware of the benefits ...

    Pro WPF in C# 2010 Mar 2010

    After giving you a firm foundation, it goes on to explore the more advance aspects of WPF and how they relate to the others elements of the .NET 4.0 platform and associated technologies such as ...

    Pro WPF and Silverlight MVVM-English

    However, the knowledge of how to do this is missing from a large part of the development community―even amongst those who work with WPF and Silverlight on a daily basis. Too often there is a reliance...

    Applied WPF 4 in Context

    By the end of the book, you should have a working knowledge of WPF and know how to architect a WPF application using the tools provided by Microsoft, such as SQL Server 2008 R2 Express Edition, the ...

    applied wpf 4 in 2010

    a component to access the data, a component to include a logical function, a component to render the user interface, and so on. In this book, I will show you how to create and implement WPF, using ...

    InteractiveDataDisplay.WPF

    在窗口中实现绘图功能,并能够实现动态绘制,而且图表可交互

    WCF & WPF 聊天程序源码

    &lt;br&gt;This article is about how to create a peer-to-peer chat application using Windows Communication Foundation (WCF) and also how to make it look nice using Windows Presentation Foundation (WPF)....

    Professional.WPF.Programming

    If you want to learn how to build killer user interfaces for Windows and the web, then this book is for you. It arms you with the tools and code you'll need to effectively utilize the Windows ...

    InteractiveDataDisplay.WPF.rar

    InteractiveDataDisplay x轴显示时间

    Telerik WPF Controls Tutorial 无水印pdf 2014

    Use the new model for using DataContext to validate a WPF window Employ the Telerik interface classes to load controls Understand object-oriented concepts such as inheritance and interfaces Secure an ...

    WPF全景控件Panorama源码

    I say Style, as it may not be 100% in line with what the Win8 Metro tile interface does, or how it functions, but to be honest, it fitted my needs well enough and I figured it may be OK for others....

    WPF Control Development Unleashed

    The authors begin by explaining how to “think in WPF,” and then introduce powerful new techniques for everything from handling 3D layouts to creating game-like physics effects. Along the way, they ...

    Packt.Mastering.Windows.Presentation.Foundation.2017 pdf文字版

    Learn how to use the MVVM software architectural pattern and see the benefits of using it with Windows Presentation Fountain (WPF) Learn which controls to use in particular situations and the various...

    Professional WPF Programming

    touch on a bit of everything WPF has to offer, so you know not only what’s provided by the platform, but also how to utilize it. Of course, because it’s a large platform, we won’t be able to cover ...

    C# wpf 多线程

    The CSWPFThreading sample project illustrates two WPF threading models. The first one divides a long-running ...* also want to keep the GUI responsive when doing expensive operations in * the UI thread.

    WPF LINQ to SQL 类上传下载删除图片

    闲暇时,写了个WpfDBOperateImage程序,此程序基于WPF 框架并通过创建LINQ to SQL 类进行上传、下载、删除图片,帮助初学者的你快速入门。

    Wrox.Professional.WPF.Programming(2007)-2

    ”, “How do I start using WPF?” and “What does WPF have to offer me?” are answered early in the first chapter, followed swiftly by a detailed look at the subsystems and graphical features offered ...

Global site tag (gtag.js) - Google Analytics