我无法获得绑定工作。我创造了一个完全没有结果的例子来证明我的问题。就像这样......
我有一组我希望能够在XAML中定义的小部件。此集合将与UserControl关联。在XAML中,我想将小部件的“Name”属性绑定到数据位(本例中为字符串)。
因此,对于代码,我有一个从DependencyObject派生的Widget类
public class Widget : DependencyObject
{
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(Widget), new UIPropertyMetadata("--widget--"));
}
请注意,此属性的默认值为“--widget--”。我也有一个WidgetCollection类......
public class WidgetCollection : Collection<Widget>
{
public WidgetCollection()
{
}
}
WidgetControl是WidgetCollection的父级,它作为名为“Widgets”的属性公开
[ContentPropertyAttribute("Widgets")]
public partial class WidgetControl : UserControl
{
public WidgetCollection Widgets
{
get { return (WidgetCollection)GetValue(WidgetsProperty); }
set { SetValue(WidgetsProperty, value); }
}
// Using a DependencyProperty as the backing store for Widgets. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WidgetsProperty =
DependencyProperty.Register("Widgets", typeof(WidgetCollection), typeof(WidgetControl), new UIPropertyMetadata(null));
public WidgetControl()
{
Widgets = new WidgetCollection();
InitializeComponent();
}
public IEnumerable<string> GetWidgetNames()
{
return Widgets.Select(w => w.Name);
}
}
对于视觉反馈,WidgetControl显示一个红色矩形......
<UserControl x:Class="StackOverflow.BindingProblem.WidgetControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Rectangle Margin="0" Fill="Red"/>
</Grid>
</UserControl>
所以现在我已经获得了演示的所有部分,我将它们放在MainWindow中......
<Window x:Class="StackOverflow.BindingProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:StackOverflow.BindingProblem"
Title="MainWindow" Height="220" Width="160"
x:Name="x_win">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<l:WidgetControl x:Name="x_WidgetControl" Grid.Row="0">
<l:Widget Name="Sprocket"/>
<l:Widget Name="{Binding Path=WidgetName1, ElementName=x_win}"/>
<l:Widget Name="{Binding Path=WidgetName2, ElementName=x_win}"/>
<l:Widget Name="Wrench"/>
</l:WidgetControl>
<StackPanel Orientation="Vertical" Grid.Row="1">
<TextBlock Text="Sprocket"/>
<TextBlock Text="{Binding Path=WidgetName1, ElementName=x_win}"/>
<TextBlock Text="{Binding Path=WidgetName2, ElementName=x_win}"/>
<TextBlock Text="Wrench"/>
</StackPanel>
<ListBox x:Name="x_ListBox" Grid.Row="2"/>
</Grid>
</Window>
在这里,我已将结果转储到窗口中,这样您就可以在不使用调试器的情况下查看我正在谈论的内容。我正在使用网格来创建三行。顶部显示了WidgetControl(一个令人兴奋的红色矩形!),我在XAML中定义了4个小部件。请注意,其中两个小部件具有硬编码名称,另外两个小部件的名称数据绑定到MainWindow类上定义的字符串属性。中间一行显示四个具有 完全相同 绑定的TextBlock。底行显示了一个列表框。此列表框中填充了WidgetControl拥有的WidgetCollection中的窗口小部件的名称。此列表在加载窗口后收集,因此在数据绑定完成后收集。
背后的MainWindow代码看起来像这样......
public partial class MainWindow : Window
{
public MainWindow()
{
Loaded += new RoutedEventHandler(MainWindow_Loaded);
InitializeComponent();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
x_ListBox.ItemsSource = x_WidgetControl.GetWidgetNames();
}
public string WidgetName1
{
get { return "Crank"; }
}
public string WidgetName2
{
get { return "Wheel"; }
}
}
当这个演示运行时,窗口看起来像这样......
[大鼠!因为我是新的提交者而省略了图片]我将用文字嘲笑它......
-----------
| |
| | <-- red rectangle (the WidgetControl)
| |
-----------
Sprocket
Crank <-- textblocks
Wheel
Wrench
-----------
Sprocket
--widget-- <-- listbox
--widget--
Wrench
-----------
注意TextBlocks上的绑定是如何工作的,但是Widgets上的绑定却没有。底行显示不成功的绑定为--widget--而不是Crank and Wheel。
那为什么会发生这种情况?如何让绑定工作?
答案 0 :(得分:0)
我只是在黑暗中拍摄,但我认为您的DependencyProperty名称已正确绑定,但当它从“--widget--”更改为“Crank”时,更改不会传播到名称的任何位置被展示。您需要在DependencyProperty.Register上设置回调。
Widget究竟做了什么?
答案 1 :(得分:0)
好吧,我找到了一些答案。这两种技术似乎都可以解决问题,而且两者都非常有用。作为一张新的海报,我只能提交一个超链接。因此,您可以搜索“将虚拟分支附加到逻辑树 - 由Josh Smith”,和/或您可以转到此链接以获取我最喜欢的...
就个人而言,我喜欢从Freezable派生我的Widget,因为它需要较少的plumming并且对初始化顺序不敏感.Josh的解决方案只有在DataContext设置为 AFTER 时才会起作用InitializeComponent()被称为,如此......
public MainWindow()
{
Loaded += new RoutedEventHandler(MainWindow_Loaded);
InitializeComponent();
DataContext = this;
}
注意:在我的例子中,仅从Freezable派生Widget是不够的。我还必须从FreezableCollection派生WidgetCollection !!
案件结案。