Привязка стихий Silverlight4
Я немного новичок.net, и я работаю над своим первым большим проектом Silverlight. Так что извините за отсутствие жаргона и длины вопроса. Но моя проблема заключается в следующем.
Проект строится по шаблону MVVM (в данном случае я использую LightMVVM). Большинство представлений содержат списки. Эти списки должны обрабатывать несколько различных типов данных, каждый из которых имеет свой визуальный вид. После некоторого возни я расшифровал tp, попробуйте эту реализацию для выбора таблицы данных:
http://silverscratch.blogspot.com/2010/04/changing-data-templates-at-run-time.html
Некоторые из моих предметов, однако, имеют вспомогательные элементы управления, которые должны общаться с моделью представления. Из того, что я читал, Команды с привязками элементов - лучший способ справиться с этим.
Так, например:
<Grid x:Name="NavMainLayoutRoot" DataContext="{Binding Source={StaticResource NavMainViewModelDataSource}}" Margin="15,0,0,0">
....
<ListBox x:Name="MenuListBox" HorizontalAlignment="Left" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource MainNavigationButtonStyle}" Padding="0" VerticalAlignment="Top" >
<ListBox.RenderTransform>
<CompositeTransform/>
</ListBox.RenderTransform>
<ListBox.ItemTemplate>
<DataTemplate>
<xxxControls:SelectableContentControl TemplateName="{Binding Path=Type}" Content="{Binding Details}" IsTabStop="{Binding IsHitTestEnabled}">
<xxxControls:SelectableContentControl.Templates>
<DataTemplate>
<local:GenericItem />
</DataTemplate>
<DataTemplate x:Name="navbutton">
<local:MainNavItem />
</DataTemplate>
</xxxControls:SelectableContentControl.Templates>
</xxxControls:SelectableContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
....
И MainNavItem, упрощенный это:
<Grid x:Name="NavItemRoot" VerticalAlignment="Top" Margin="0,0,0,0">
<Button Content="{Binding Label}" VerticalAlignment="Top" Style="{StaticResource MainNavItemButtonStyle}" HorizontalAlignment="Left" Margin="5,0" Command="{Binding DataContext.NavButtonClick, ElementName=NavMainLayoutRoot}"/>
</Grid>
Проблема в том, что это не сработало. Так что ради ухмылки я пошел дальше, скопировал и вставил код для MainNavItem прямо в тег, и, как по волшебству, он начал работать.
Так как я многократно использую множество этих шаблонов элементов по всему приложению, очень приятно иметь их во вложенных внешних файлах, и я не хочу от них отказываться.
((Если подумать, этот пример не самый лучший, достаточно сказать, что некоторые из этих шаблонов данных содержат несколько элементов управления, и я не могу просто использовать selected Item в списке для обработки выбранных событий.))
Так что любые предложения приветствуются. Какова лучшая практика здесь?
1 ответ
Моя первая мысль - что-то в вашем пользовательском элементе управления MainNavItem устанавливает свой DataContext на что-то другое. Если вы не установите DataContext, он должен автоматически выбрать его из текущего элемента в вашем MenuListBox.
Вы можете попробовать создать конвертер тестовых значений и поместить в него точку останова, чтобы проверить контекст данных во время выполнения.
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value; // put break point here to test data binding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value;
}
}
И измените ваш MainNavItem, чтобы он выглядел так, чтобы разрывать TestConverter во время выполнения.
<UserControl.Resources>
<ResourceDictionary>
<TestConverter x:Key="TestConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="NavItemRoot" DataContext="{Binding Converter={StaticResource TestConverter}}">
<Button Content="{Binding Path=Label, Converter={StaticResource TestConverter}}" />
</Grid>
Это поможет вам определить проблему с привязкой данных.
Я подозреваю, что проблема с вашей командой в том, что вы используете привязку данных от элемента к элементу, чтобы попытаться привязать элемент, находящийся вне пользовательского элемента управления, в котором вы находитесь. Это не сработает. Вместо этого попробуйте настроить статический ресурс NavMainViewModelDataSource в App.xaml, после чего вы сможете напрямую связать его с вашим пользовательским элементом управления.
<Button Content="{Binding Label}" Command="{Binding Path=NavButtonClick, Source={StaticResource NavMainViewModelDataSource}}" />