问题
I’m having trouble using a DataContextProxy in my WPF application. When I place a DataContextProxy in the Resources section of a Grid it is never loaded. If I move the DataContextProxy out of the resource section everything works correctly.
I’ve been investigating this for some time and have tried a number of methods to debug the application.
I’ve placed a DebugConverter on the control that I’m trying to use the Proxy with. The Debug converter is never called.
I’ve used WPFSnoop to see if there are any binding errors. I get the following binding error on the DataContextProxy,
System.Windows.Data Error: 3 : Cannot find element that provides DataContext. BindingExpression:(no path); DataItem=null; target element is 'Proxy' (Name=''); target property is 'DataContext' (type 'Object')
I’ve placed a breakpoint on the loaded event of my DataContextProxy. The loaded event is never called and I’ve placed a breakpoint in the DataContextChanged event which is never called.
Here is some sample code to demonstrate this. Obviously I know I do not really need to use a DataContextProxy on the TextBox.
<Window x:Class="WpfDataContextProxyBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfDataContextProxyBug"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:DebugConverter x:Key="DebugConverter"/>
</Window.Resources>
<Grid>
<Grid.Resources>
<local:Proxy x:Key="Proxy" DataContext="{Binding}" />
</Grid.Resources>
<TextBox DataContext="{Binding Path=Name, Source={StaticResource Proxy}, Converter={StaticResource DebugConverter}}"/>
</Grid>
</Window>
The DataContextProxy class
public class Proxy : FrameworkElement
{
public Proxy()
{
Loaded += DataContextProxy_Loaded;
DataContextChanged += Proxy_DataContextChanged;
}
void Proxy_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
}
void DataContextProxy_Loaded(object sender, RoutedEventArgs e)
{
}
}
回答1:
I've also hit this problem when I tried to use the DataContextProxy in WPF. I've come up with a solution inspired by it which seems to handle the job pretty decently. Check it out:
public class DataContextProxyBehavior : Behavior<FrameworkElement>
{
public Object DataSource
{
get { return (Object)GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof(Object), typeof(DataContextProxy), null);
protected override void OnAttached()
{
base.OnAttached();
// Binds the target datacontext to the proxy,
// so whenever it changes the proxy will be updated
var binding = new Binding();
binding.Source = this.AssociatedObject;
binding.Path = new PropertyPath("DataContext");
binding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(this, DataContextProxyBehavior.DataSourceProperty, binding);
// Add the proxy to the resource collection of the target
// so it will be available to nested controls
this.AssociatedObject.Resources.Add(
"DataContextProxy",
this
);
}
protected override void OnDetaching()
{
base.OnDetaching();
// Removes the proxy from the Resources
this.AssociatedObject.Resources.Remove(
"DataContextProxy"
);
}
}
You just need to attach it to the parent element. The static resource reference in the child element will remain the same. I've posted an usage example here.
来源:https://stackoverflow.com/questions/10446689/wpf-datacontextproxy-in-resources-section