Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 嵌套的UserControls数据上下文_C#_Wpf - Fatal编程技术网

C# 嵌套的UserControls数据上下文

C# 嵌套的UserControls数据上下文,c#,wpf,C#,Wpf,摘要: 我有两个名为Zone和ZoneGroup的UserControls。其中一个控件(ZoneGroup)包括另一个控件(Zone)的两个实例。它们都在加载的事件处理程序中将根元素的DataContext设置为this 问题是在加载之前设置了内部控件(区域s)的DataContext(加载之前发生的DataContextChanged事件),这导致UI中出现一些故障。(在区域内控件的初始状态是错误的。)如果我阻止它,一切都正常(至少看起来是这样!)除了我遇到以下错误报告。(在输出窗口中) S

摘要:

我有两个名为
Zone
ZoneGroup的
UserControl
s。其中一个控件(
ZoneGroup
)包括另一个控件(
Zone
)的两个实例。它们都在加载的
事件处理程序中将根元素的
DataContext
设置为
this

问题是在加载之前设置了内部控件(
区域
s)的
DataContext
(加载
之前发生的
DataContextChanged
事件),这导致UI中出现一些故障。(在
区域内
控件的初始状态是错误的。)如果我阻止它,一切都正常(至少看起来是这样!)除了我遇到以下错误报告。(在输出窗口中)

System.Windows.Data错误:40:BindingExpression路径错误:在“对象”“分区组”(名称=“”)上找不到“ZoneBrush”属性。BindingExpression:Path=ZoneBrush;DataItem='ZoneGroup'(名称='');目标元素为“brdRoot”(名称=“”);目标属性为“BorderBrush”(类型为“Brush”)

详细信息:

有一个名为
Zone
UserControl
包含如下几个数据绑定

<UserControl x:Class="MyApp.Zone"
    ∙∙∙>
    <Border x:Name="brdRoot" BorderBrush="{Binding ZoneBrush}" BorderThickness="1">
        ∙∙∙
    </Border>
</UserControl>
另外,还有另一个
UserControl
,它有两个
ContentPresenter
s,以便包含和管理两个
区域
控件

<UserControl x:Class="MyApp.ZoneGroup"
    ∙∙∙>
    <Border x:Name="brdRoot" BorderBrush="Gray" BorderThickness="1">
        <StackPanel Orientation="Horizontal">
            <ContentPresenter Content="{Binding MainZone}"
                              Margin="{Binding MainZonePadding}"/>
            <ContentPresenter Content="{Binding MemberZone}"/>
        </StackPanel>
    </Border>
</UserControl>

编辑► 草图:

我的应用程序工作正常,但报告了一些BindingExpression错误。

这不是一个直接的答案

正如@HighCore所说,我尝试使用
ItemsControl
,而不是在我的用户控件中实现两个
ContentPresenter
s。为了清晰起见,我制作了一个新的简单应用程序,可以简单地描述它。因此,请考虑一些新的假设:

这里同样有两个
UserControl
s
MyItem
MyItemsControl
如下所示

<UserControl x:Class="MyApp.MyItem"
             ∙∙∙>
    <Grid x:Name="grdRoot">
        <Border BorderBrush="{Binding ItemBorderBrsuh}" BorderThickness="1">
            <TextBlock x:Name="txtColorIndicator"
                       Text="Item"
                       TextAlignment="Center"
                       Margin="5"/>
        </Border>
    </Grid>
</UserControl>
这是MyItemsControl

<UserControl x:Class="MyApp.MyItemsControl"
    ∙∙∙>
    <StackPanel>
        <TextBlock x:Name="txtHeader" Margin="0,0,0,5" TextAlignment="Center" Text="0 Item(s)"/>
        <Border BorderBrush="Gray" BorderThickness="1" Padding="5">
            <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <local:MyItem />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>
    </StackPanel>
</UserControl>
现在,
BindingExpression
s没有问题,但是一个重要的问题仍然存在。如何更换

{
    grdRoot.DataContext = this;
}

使用真实的
视图模型

屏幕截图:



编辑:我尝试实现MVVM模式,但存在一些问题。我问了第一个问题。

你把它太复杂了,所有那些
用户控件
和所有那些
依赖属性
。看看这个使用0行C#代码(仅限XAML)的示例:


ItemsControl的样式:

        <Style TargetType="ItemsControl" x:Key="ZoneItemsControlStyle">
            <Setter Property="BorderBrush" Value="Black"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="Padding" Value="5"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ItemsControl">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                Padding="5">
                            <DockPanel>
                                <TextBlock HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                           Text="{Binding Items.Count,RelativeSource={RelativeSource TemplatedParent}, StringFormat='{}{0} Item(s)'}"
                                           Foreground="{TemplateBinding Foreground}"
                                           DockPanel.Dock="Top"/>
                                <Border BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        Padding="{TemplateBinding Padding}">
                                    <ItemsPresenter/>
                                </Border>
                            </DockPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>

刷子的数据模板:

        <DataTemplate DataType="{x:Type Brush}">
            <Border BorderBrush="{Binding}" Margin="1" BorderThickness="1" Padding="2,3,2,3">
                <TextBlock Text="{Binding}" TextAlignment="Center" Foreground="Black"/>
            </Border>
        </DataTemplate>

    </Window.Resources>

现在,它的用法是:

    <Grid>
        <ItemsControl VerticalAlignment="Center" HorizontalAlignment="Center"
                      Style="{StaticResource ZoneItemsControlStyle}">
            <SolidColorBrush Color="Red"/>
            <SolidColorBrush Color="Green"/>
            <SolidColorBrush Color="Black"/>
            <SolidColorBrush Color="Blue"/>
        </ItemsControl>
    </Grid>
</Window>

结果:

查看我如何使用
数据模板
,以显示特定
数据类型的自定义UI?(在本例中,
System.Windows.Media.Brush
class)

我正在“使用画笔作为视图模型”。当然,您也可以创建自己的ViewModels,然后为每种VM类型创建特定的
DataTemplate

另外,请参见如何使用
TemplateBinding
MarkupExtension将
ControlTemplate
中的多个属性绑定到
ItemsControl
实例中的相应值

最后,了解如何将
任何类型的项目添加到
ItemsControl

<Grid>
    <local:MyItemsControl HorizontalAlignment="Center" VerticalAlignment="Center" Padding="5" BorderBrush="Black" BorderThickness="1">
        <local:MyItemsControl.Items>
            <local:MyItem ItemBorderBrsuh="Green" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Red" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Blue" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Orange" Margin="1"/>
        </local:MyItemsControl.Items>
    </local:MyItemsControl>
</Grid>

另外,我必须提到,为了实现可重用性,我使用了这种基于
风格的方法。您可以将另一个
ItemsControl
放置在应用程序的其他位置,并设置其
Style=“{StaticResource ZoneItemsControlStyle}”
即可。但是如果您只计划使用一次,您可以将所有硬编码的属性放在
ItemsControl.Template
ControlTemplate中。

这完全是错误的。这就是它出现故障的原因,因此,您的
UserControl
s不是存储数据的正确位置。改为创建一个ViewModel,您将不会遇到这些问题。@HighCore您介意解释更多吗?我应该怎么做?发布一个你需要的和你当前拥有的屏幕截图。听起来不错,除了任何给定UI元素的
DataContext
应该是它相应的ViewModel,而不是它本身。然后,如果需要绑定到可视化树中的父属性,请使用
RelativeSource
bindings。此外,包含多个项的容器是
ItemsControl
,而不仅仅是具有某些属性的自定义usercontrol。
<Grid>
    <local:MyItemsControl HorizontalAlignment="Center" VerticalAlignment="Center" Padding="5" BorderBrush="Black" BorderThickness="1">
        <local:MyItemsControl.Items>
            <local:MyItem ItemBorderBrsuh="Green" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Red" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Blue" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Orange" Margin="1"/>
        </local:MyItemsControl.Items>
    </local:MyItemsControl>
</Grid>
{
    grdRoot.DataContext = this;
}
{
    this.DataContext = this;
}
<Window x:Class="MiscSamples.ItemsControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ItemsControl" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="ItemsControl" x:Key="ZoneItemsControlStyle">
            <Setter Property="BorderBrush" Value="Black"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="Padding" Value="5"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ItemsControl">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                Padding="5">
                            <DockPanel>
                                <TextBlock HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                           Text="{Binding Items.Count,RelativeSource={RelativeSource TemplatedParent}, StringFormat='{}{0} Item(s)'}"
                                           Foreground="{TemplateBinding Foreground}"
                                           DockPanel.Dock="Top"/>
                                <Border BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        Padding="{TemplateBinding Padding}">
                                    <ItemsPresenter/>
                                </Border>
                            </DockPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <DataTemplate DataType="{x:Type Brush}">
            <Border BorderBrush="{Binding}" Margin="1" BorderThickness="1" Padding="2,3,2,3">
                <TextBlock Text="{Binding}" TextAlignment="Center" Foreground="Black"/>
            </Border>
        </DataTemplate>

    </Window.Resources>
    <Grid>
        <ItemsControl VerticalAlignment="Center" HorizontalAlignment="Center"
                      Style="{StaticResource ZoneItemsControlStyle}">
            <SolidColorBrush Color="Red"/>
            <SolidColorBrush Color="Green"/>
            <SolidColorBrush Color="Black"/>
            <SolidColorBrush Color="Blue"/>
        </ItemsControl>
    </Grid>
</Window>