Я работаю над проектом Silverlight, используя MVVM, и столкнулся с проблемой, которая возникает только в некоторых довольно специфических ситуациях. Я постарался максимально сократить все, чтобы остались только важные части.
Сценарий:
- Стандартный Silverlight
ChildWindow
-
ChildWindow
имеет элемент управления Selector
(например, ComboBox
или ListBox
).
-
ChildWindow
имеет ContentPresenter
-
Content
этого ContentPresenter
связан с SelectedValue
вышеупомянутого Selector
элемента управления (На самом деле он связан со свойством ViewModel, но для целей тестирования это не обязательно).
-
ContentPresenter
использует DataTemplateSelector , чтобы определить, ContentTemplate
- Элемент управления
Selector
содержит string
значения «A» и «B», которые соответствуют DataTemplate
s «TemplateA» и «TemplateB».
- «TemplateB» содержит элемент управления
TimePicker
.
Проблема:
После выбора «B» (следовательно, загрузки «TemplateB») при следующей попытке изменить выбранный шаблон веб-страница хоста замерзнет. Не выдается никаких исключений и никакой информации не предоставляется.
Примечания:
- Все отлично работает за пределами
ChildWindow
.
- Все работает нормально, если ни один из шаблонов не содержит элемент управления
TimePicker
.
- Элемент управления
TimePicker
работает нормально, если отображается без использования ContentPresenter
/ DataTemplateSelector
.
- Я посмотрел на TimePicker в ChildWindow вызывает исключение на странице CodePlex набора инструментов Silverlight. Эта конкретная проблема, похоже, решена, и я попытался внедрить предложенный обходной путь , просто чтобы быть уверенным, и он не имеет никакого эффекта.
Код для воспроизведения проблемы:
ChildWindow
XAML:
<controls:ChildWindow
x:Class="TimePickerProblem.ChildWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:local="clr-namespace:TimePickerProblem"
Width="400"
Height="300"
Title="ChildWindow1">
<controls:ChildWindow.Resources>
<local:ViewModel
x:Key="vm" />
</controls:ChildWindow.Resources>
<Grid>
<Grid
x:Name="LayoutRoot"
Background="White"
DataContext="{StaticResource vm}">
<StackPanel
HorizontalAlignment="Center">
<ComboBox
x:Name="ComboBox"
Margin="20"
ItemsSource="{Binding Templates}" />
<ContentPresenter
Content="{Binding ElementName=ComboBox, Path=SelectedValue}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<local:TemplateSelector
Content="{Binding}">
<local:TemplateSelector.TemplateA>
<DataTemplate>
<TextBlock
Text="Hello from A" />
</DataTemplate>
</local:TemplateSelector.TemplateA>
<local:TemplateSelector.TemplateB>
<DataTemplate>
<toolkit:TimePicker />
</DataTemplate>
</local:TemplateSelector.TemplateB>
</local:TemplateSelector>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</StackPanel>
</Grid>
<Button
x:Name="CancelButton"
Content="Cancel"
Click="CancelButton_Click"
Width="75"
Height="23"
HorizontalAlignment="Right"
Margin="0,12,0,0"
Grid.Row="1" />
<Button
x:Name="OKButton"
Content="OK"
Click="OKButton_Click"
Width="75"
Height="23"
HorizontalAlignment="Right"
Margin="0,12,79,0"
Grid.Row="1" />
</Grid>
ViewModel:
public List<string> Templates { get { return new List<string>() { "a", "b" }; } }
DataTemplateSelector:
public class TemplateSelector : DataTemplateSelector
{
public DataTemplate TemplateA { get; set; }
public DataTemplate TemplateB { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
string value = (string)item;
switch (value.ToLower())
{
case "a":
return TemplateA;
case "b":
return TemplateB;
default:
return base.SelectTemplate(item, container);
}
}
}