Привязка стихий Silverlight4 - PullRequest
0 голосов
/ 05 августа 2010

Я немного новичок .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 прямо в тег и, как по волшебству, он начал работать.

Поскольку я многократно использую многие из этих шаблонов элементов по всему приложению, иметь их в красивых внешних файлах - это очень приятно , и я не хочу от них отказываться.

((Если подумать, этот пример не самый лучший, достаточно сказать, что некоторые из этих шаблонов данных содержат несколько элементов управления, и я не могу просто использовать selectedItem в списке для обработки выбранных событий.))

Так что любые предложения приветствуются. Какая лучшая практика здесь?

1 Ответ

0 голосов
/ 05 августа 2010

Моя первая мысль - что-то в вашем пользовательском элементе управления 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}}" />
...