我已经尝试了许多类似问题提出的解决方案,但似乎仍然无法正常工作。
我有一个名为 LayoutView 的自定义 TabControl(见下文 XAML)它使用一个名为 LayoutViewModel 的视图模型(见下文,{不包括转换器})
设计器本身显示良好(见下图)我的问题是如何将正确的 DataContext 注入自定义控件。我尝试添加一个 LayoutViewModel 属性主视图模型并引用它,但我得到的只是一个空白屏幕/控件。
我怀疑这可能与在自定义 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 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>
它的视图模型
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
}
}