WPF vs. Silverlight - 资源中的数据绑定

4

在进行了一段时间的Silverlight开发之后,我目前正在进行一些WPF工作...

我经常使用这个技巧来使我的一些ValueConverters更加方便:

public class MyCovnerterWithDataContext : FrameworkElement, IValueConverter
{
    private MyDataContextType Data
    { 
        get { return this.DataContext as MyDataContextType; }
    }
    ....

现在我可以在转换器方法中访问我的DataContext,这对于许多情况非常方便,您可以想象得到。
我尝试在WPF中使用同样的技巧,但不幸的是这根本不起作用。 调试输出中会出现以下错误:
“找不到提供DataContext的元素”
我认为资源在Silverlight中是视觉树的一部分,而在WPF中则不是。
那么 - 我的小技巧在WPF中是否可行? 我的小技巧是否应被视为肮脏的黑客技术?
您有什么看法和建议?
问候 约翰内斯
更新: 根据要求,以下是更多信息 - 实际上是一个最小化的示例:
XAML:
    <Window x:Class="WpfDataContextInResources.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfDataContextInResources"
            x:Name="window"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:TestWrapper x:Key="TestObj" />
        </Window.Resources>
        <StackPanel>
            <TextBlock Text="{Binding Text}" />
            <TextBlock Text="{Binding DataContext.Text, Source={StaticResource TestObj}, FallbackValue='FALLBACK'}" />
        </StackPanel>
    </Window>

这是一个 .cs 文件:

    namespace WpfDataContextInResources
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new DataClass()
                    {
                        Text = "Hello",
                    };
            }
        }

        public class TestWrapper : FrameworkElement {}

        public class DataClass
        {
            public string Text { get; set; }
        }
    }

至少在我的电脑上,下方的文本块保持了回退值。

更新 #2:

我尝试了Martin提出的建议(派生自DependencyObject、创建自己的DependencyProperty等),但它也没有起作用。不过这次错误信息是另一种:

"System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'TestWrapper' (HashCode=28415924); target property is 'TheData' (type 'Object')"

我也有一些解决方法的建议:

1.) - 使用MultiBinding --> 与Silverlight不兼容,在某些情况下不足够。

2.) - 使用另一个包装对象,在代码后台手动设置DataContext,像这样 --> 与Silverlight完全兼容(除了不能直接使用Framework-Element之外 - 必须制作一个继承自它的空类)

xaml:

<Window.Resources>
    <FrameworkElement x:Key="DataContextWrapper" />
    <local:TestWrapper x:Key="TestObj" DataContext="{Binding DataContext, Source={StaticResource DataContextWrapper}}" />
    ...

后端代码:

 //of course register this handler!
 void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
 {
        var dcw = this.Resources["DataContextWrapper"] as FrameworkElement;
        dcw.DataContext = this.DataContext;
 }

有趣。对于我来说(一个Silverlight开发者),使用一个存根化的MyDataContextType,这段代码可以编译并运行。请提供更多关于这个IValueConverter尝试做什么的信息... - Gayot Fow
1个回答

0

你的类型可能存在问题,因为它派生自FrameworkElement: 请参考ResourceDictionaries中适合对象的MSDN页面

[...] 必须是可共享的 [...] 任何从UIElement类型派生的对象本质上都是不可共享的 [...]

应该改为派生自DependencyObject

public class TestWrapper : DependencyObject {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接