将自定义控件绑定到父datacontext属性

时间:2015-12-10 00:39:24

标签: c# wpf mvvm datacontext childcontrol

我尝试过类似问题提出的许多解决方案,但似乎仍然无法实现这一点。

我有一个名为LayoutView的自定义TabControl(参见下面的XAML) 它使用名为LayoutViewModel的视图模型(参见下面的{不包括转换器})

设计师本身显示正常(见下图) 我的问题是如何将正确的DataContext注入自定义控件。 我尝试添加一个LayoutViewModel属性主视图模型并引用它,但我得到的只是一个空白屏幕/控件。

我怀疑它可能与在Custom TabControl中设置DataContext有关,但如果我删除它就会出现严重错误。

有人可以告诉我正确的方法。

干杯 杰夫

主控制

<UserControl x:Class="Layout.Performances.Views.LT"
             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" 
            xmlns:v="clr-namespace:Layout.Performances.Views"
            xmlns:vm="clr-namespace:Layout.Performances.ViewModels"
            mc:Ignorable="d"
            DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
            d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, 
                    Type={x:Type vm:PerformanceGraphicViewModelDesignData}}"
             d:DesignHeight="491" d:DesignWidth="502">
    <Grid>
        <!--<v:LayoutView x:Name="Lv" ItemsSource="{Binding Layout}" />-->
        <!--<v:LayoutView DataContext="DataContext.Lvm" />-->
        <v:LayoutView DataContext="{Binding ElementName=LT, Path=DataContext.Lvm}" />
    </Grid>
</UserControl> 

自定义TabControl

<TabControl x:Class="Layout.Performances.Views.LayoutView"
         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" 
         xmlns:sys="clr-namespace:System;assembly=mscorlib"
         xmlns:pbs="clr-namespace:Layout;assembly=Layout"
         mc:Ignorable="d"
         xmlns:localcvt="clr-namespace:Layout.Performances.Views.Converters"
         xmlns:vm="clr-namespace:Layout.Performances.ViewModels"
         xmlns:muibehav="clr-namespace:Layout.MUI.Windows.Behaviors;assembly=Layout.MUI"
         DataContext="{Binding RelativeSource={RelativeSource Self}}"
         d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type vm:LayoutViewModelDesignData}}"
         ItemsSource="{Binding Layout.PerformanceSections}"
         SelectedItem="{Binding SelectedSection, Mode=TwoWay}"
         ItemTemplate="{DynamicResource HeaderTemplate}"
         muibehav:TabContent.IsCached="True"
         Height="1000" Width="1000"
         >

<TabControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Layout.MUI;component/AssetsPB/ModernUI.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <localcvt:SeatPositionConverter x:Key="SeatPositionConverter" />
        <localcvt:AreaSizeConverter x:Key="AreaSizeConverter" />
        <localcvt:ColorFromArgbConverter x:Key="ColorFromArgbConverter" />
        <sys:Double x:Key="Buttonwidth">24</sys:Double>
        <sys:Double x:Key="Buttonpadding">2</sys:Double>

        <DataTemplate x:Key="HeaderTemplate">
            <Grid>
                <TextBlock TextWrapping="Wrap" Text="{Binding Description, Mode=OneWay}" />
            </Grid>
        </DataTemplate>

        <ControlTemplate x:Key="TabItemControlTemplate" TargetType="{x:Type TabItem}">
            <Grid SnapsToDevicePixels="True">
                <Border CornerRadius="12" x:Name="Bd" BorderBrush="Red" BorderThickness="1" Padding="{TemplateBinding Padding}">
                    <ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding HeaderTemplate}" 
                                  Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" 
                                  ContentSource="Header" 
                                  HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                  VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
                </Border>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>

</TabControl.Resources>

<!--Sections-->
<muibehav:TabContent.Template>
    <!--Section-->
    <DataTemplate x:Name="SectionContentTemplate" DataType="{x:Type pbs:PerformanceSection}">
        <Canvas>
            <Canvas.RenderTransform>
                <ScaleTransform ScaleX="1" ScaleY="1"  ></ScaleTransform>
            </Canvas.RenderTransform>
            <!--Stage-->
            <Grid>
                <Grid.Style>
                    <Style TargetType="Grid">
                        <Setter Property="Canvas.Top" Value ="{Binding StageTopPos}"/>
                        <Setter Property="Canvas.Left" Value ="{Binding StageLeftPos}"/>
                    </Style>
                </Grid.Style>
                <Label BorderBrush="BlueViolet" BorderThickness="2">This is another the Stage</Label>
            </Grid>
            <!--Areas-->
            <ItemsControl ItemsSource="{Binding PerformanceAreas}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas>

                        </Canvas>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Top" Value ="{Binding TopPos}"/>
                        <Setter Property="Canvas.Left" Value ="{Binding  LeftPos}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemTemplate>
                    <!--Area-->
                    <DataTemplate DataType="{x:Type pbs:PerformanceArea}">
                        <Canvas>
                            <Canvas.RenderTransform>
                                <RotateTransform CenterX="0.5" CenterY="0.5" Angle="-10"></RotateTransform>
                            </Canvas.RenderTransform>
                            <Border Padding="1,0" BorderBrush="LightGray" BorderThickness="1" CornerRadius="5,5,0,0" 
                                    Canvas.Left="{StaticResource Buttonpadding}">
                                <TextBlock Text="{Binding Description}" FontSize="10"/>
                            </Border>
                            <Grid Margin="0" Canvas.Top="14">
                                <Grid.Height>
                                    <MultiBinding Converter="{StaticResource AreaSizeConverter}">
                                        <Binding Path="Height" />
                                        <Binding Path="Width" />
                                        <Binding Path="Orientation" />
                                        <Binding Source="{StaticResource Buttonwidth}" />
                                        <Binding Source="{StaticResource Buttonpadding}" />
                                    </MultiBinding>
                                </Grid.Height>
                                <Grid.Width>
                                    <MultiBinding Converter="{StaticResource AreaSizeConverter}">
                                        <Binding Path="Width" />
                                        <Binding Path="Height" />
                                        <Binding Path="Orientation" />
                                        <Binding Source="{StaticResource Buttonwidth}" />
                                        <Binding Source="{StaticResource Buttonpadding}" />
                                    </MultiBinding>
                                </Grid.Width>
                                <Border  BorderBrush="LightGray" BorderThickness="1" CornerRadius="2">
                                    <!--Seats-->
                                    <ItemsControl ItemsSource="{Binding PerformanceSeats}" 
                                            HorizontalAlignment="Left" VerticalAlignment="Top" >
                                        <ItemsControl.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <Canvas></Canvas>
                                            </ItemsPanelTemplate>
                                        </ItemsControl.ItemsPanel>
                                        <ItemsControl.ItemContainerStyle>
                                            <Style TargetType="ContentPresenter">
                                                <Setter Property="Canvas.Top" >
                                                    <Setter.Value>
                                                        <MultiBinding Converter="{StaticResource SeatPositionConverter}">
                                                            <Binding Path="TopPos" />
                                                            <Binding Source="{StaticResource Buttonwidth}" />
                                                            <Binding Source="{StaticResource Buttonpadding}" />
                                                        </MultiBinding>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="Canvas.Left" >
                                                    <Setter.Value>
                                                        <MultiBinding Converter="{StaticResource SeatPositionConverter}">
                                                            <Binding Path="LeftPos" />
                                                            <Binding Source="{StaticResource Buttonwidth}" />
                                                            <Binding Source="{StaticResource Buttonpadding}" />
                                                        </MultiBinding>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </ItemsControl.ItemContainerStyle>
                                        <ItemsControl.ItemTemplate>
                                            <DataTemplate DataType="{x:Type pbs:PerformanceSeat}">
                                                <Button  HorizontalContentAlignment="Center"
                                                VerticalContentAlignment="Center"
                                                Width="{StaticResource Buttonwidth}"
                                                Height="{StaticResource Buttonwidth}"
                                                Padding="0">
                                                    <Button.Style>
                                                        <Style TargetType="Button" >
                                                            <Setter Property="Background" >
                                                                <Setter.Value>
                                                                    <MultiBinding Converter="{StaticResource ColorFromArgbConverter}">
                                                                        <Binding Path="SeatStatus" />
                                                                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TabControl}}" Path="DataContext.StatusColors"/>
                                                                        <Binding Path="OperatorID" />
                                                                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TabControl}}"  Path="DataContext.CurrentOperator"/>
                                                                    </MultiBinding>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Setter Property="BorderBrush" >
                                                                <Setter.Value>
                                                                    <MultiBinding Converter="{StaticResource ColorFromArgbConverter}">
                                                                        <Binding Path="SeatType.ColorARGB" />
                                                                    </MultiBinding>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Setter Property="BorderThickness" >
                                                                <Setter.Value>
                                                                    <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type TabControl}}"  Path="DataContext.SeatTypeBorder" />
                                                                </Setter.Value>
                                                            </Setter>
                                                        </Style>
                                                    </Button.Style>
                                                    <TextBlock>
                                                        <TextBlock.RenderTransform>
                                                            <RotateTransform CenterX="0.5" CenterY="0.5" Angle="10"></RotateTransform>
                                                        </TextBlock.RenderTransform>
                                                        <TextBlock.Text>
                                                            <MultiBinding StringFormat="{}{0}{1:F0}">
                                                                <Binding Path="RowID"/>
                                                                <Binding Path="SeatID"/>
                                                            </MultiBinding>
                                                        </TextBlock.Text>
                                                    </TextBlock>
                                                </Button>
                                            </DataTemplate>
                                        </ItemsControl.ItemTemplate>
                                    </ItemsControl>
                                </Border>
                            </Grid>
                        </Canvas>


                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Canvas>
    </DataTemplate>

</muibehav:TabContent.Template>

</TabControl>

其ViewModel

using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using Layout.ViewModels;

namespace Layout.Performances.ViewModels
{
    public class LayoutViewModel : ViewModelBase
    {
        public string CurrentOperator { get; set; }
        private Performance _layout;
        public Performance Layout { 
            get {
                    if (_layout == null) _layout = new Performance();
                    return _layout;
                } 
            set { _layout = value; } 
        }

        private PerformanceSection _selectedSection;

        public PerformanceSection SelectedSection
        {
            get { return _selectedSection; }
            set
            {
                _selectedSection = value;
                RaisePropertyChanged("SelectedSection");
            }
        }


        private int _seatBoarder;

        public int SeatTypeBorder
        {
            get { return _seatBoarder; }
            set { _seatBoarder = value; }
        }

        private Dictionary<string, int> _statusColors;

        public Dictionary<string,int> StatusColors
        {
            get { return _statusColors; }
            set { _statusColors = value; }
        }
        public LayoutViewModel()
        {
        }
    }
    public class LayoutViewModelDesignData : LayoutViewModel
    {
#if DEBUG
        private Dictionary<string, int> _typeCodes;

        public LayoutViewModelDesignData()
        {
            AddSections(Layout.PerformanceSections);
            SelectedSection = Layout.PerformanceSections.FirstOrDefault();
        }

        public void AddSections(EntityCollection<PerformanceSection> sections)
        {

            CurrentOperator = "PBS";
            StatusColors = new Dictionary<string, int>
            {
                {"A",-8323200},
                {"B",-32704},
                {"H",-51401},
                {"O",-13421773},
                {"R",-6710887},
                {"S",-14108161},
                {"V",-2236963},
                {"W",-6710887}
            };

            //_typeCodes = new Dictionary<string, Int32>
            //{
            //    {"AR",Convert.ToInt32(-16744193)},
            //    {"BA", Convert.ToInt32(4294902015)},
            //    {"BB", Convert.ToInt32(4278190335)},
            //    {"BC",Convert.ToInt32(4294934656)},
            //    {"D",Convert.ToInt32(-12582784)},
            //    {"PR",Convert.ToInt32(-8388544)},
            //    {"S",Convert.ToInt32(4294967295)}
            //};

            SeatTypeBorder = 2;


            var section1 = new PerformanceSection
            {
                Description = "Section 1",
                SectionID = "Section1",
                GenAdmit = "N",
                StageTopPos = 14,
                StageLeftPos = 17,
                PerformanceAreas = new EntityCollection<PerformanceArea>()
            };

            short r = 4;
            short c = 6;
            section1.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section1,
                SectionID = section1.SectionID,
                AreaID = "Area1",
                Description = "Area 1",
                LeftPos = 10,
                TopPos = 150,
                Height = r,
                Width = c,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area1", r, c)
            });

            section1.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section1,
                SectionID = section1.SectionID,
                AreaID = "Area2",
                Description = "Area 2",
                LeftPos = 600,
                TopPos = 10,
                Height = r,
                Width = c,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area2", r, c)
            });

            r = 10;
            c = 6;
            section1.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section1,
                SectionID = section1.SectionID,
                AreaID = "Area3",
                Description = "Area 3",
                LeftPos = 10,
                TopPos = 400,
                Height = r,
                Width = c,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V", "N"
                PerformanceSeats = CreateSeats("Area3", r, c)
            });

            r = 100;
            c = 12;
            section1.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section1,
                SectionID = section1.SectionID,
                AreaID = "Area4",
                Description = "Area 4",
                LeftPos = 160,
                TopPos = 50,
                Height = r,
                Width = c,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area4", r, c)
            });

            var section2 = new PerformanceSection
            {
                Description = "Section 2",
                SectionID = "Section2",
                GenAdmit = "N",
                PerformanceAreas = new EntityCollection<PerformanceArea>()
            }; 

            section2.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section2,
                SectionID = section2.SectionID,
                AreaID = "Area1",
                Description = "Area 1",
                LeftPos = 10,
                TopPos = 10,
                Height = 4,
                Width = 6,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area1", 4, 6)
            });

            section2.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section2,
                SectionID = section2.SectionID,
                AreaID = "Area2",
                Description = "Area 2",
                LeftPos = 400,
                TopPos = 10,
                Height = 4,
                Width = 6,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area2", 4, 6)
            });

            section2.PerformanceAreas.Add(new PerformanceArea
            {
                PerformanceSection = section2,
                SectionID = section2.SectionID,
                AreaID = "Area3",
                Description = "Area 3",
                LeftPos = 10,
                TopPos = 700,
                Height = 4,
                Width = 6,
                FillDirection = "H", // "H", "L", "M"
                Orientation = "H", // "H", "V"
                PerformanceSeats = CreateSeats("Area3", 4, 6)
            });

            sections.Add(section1);
            sections.Add(section2);

        }

        private static EntityCollection<PerformanceSeat> CreateSeats(string areaId, int rows, int columns)
        {
            const string rowIds = "ABCDEFGHIJKLNMOPQRSTUVWXYZ";
            const string statuses = "ABHORSVW";
            var seats = new EntityCollection<PerformanceSeat>();
            for (short row = 0; row < rows; row++)
            {
                var rowbaseidx = (int)(row/rowIds.Length);
                var rowbase = rowbaseidx == 0 ? "" : rowIds.Substring(rowbaseidx - 1, 1);
                var rowchar = rowIds.Substring((row % rowIds.Length), 1);

                for (short col = 1; col <= columns; col++)
                {
                    seats.Add(new PerformanceSeat
                    {
                        AreaID = areaId,
                        RowID = rowbase + rowchar,
                        SeatID = col,
                        SeatType = new SeatType { ColorARGB = (col % 2) == 0 ? -16744193 : -65281 },
                        SeatStatus = statuses.Substring(row % statuses.Length, 1),
                        OperatorID = (col % 2) == 0 ? "PBS" : null,
                        TopPos = (short)(row + 1),
                        LeftPos = col
                    });
                }

            }
            return seats;
        }
#endif
    }
}

enter image description here

1 个答案:

答案 0 :(得分:0)

Doh,太简单了

<v:LayoutView DataContext="{Binding Path=Lvm}" />