Привязка данных из сетки данных к компонентам пользовательского интерфейса - PullRequest
1 голос
/ 28 июня 2019

У меня есть окно с сеткой данных, получающей его элементы из ObservableCollection, и у меня есть поле на стороне, которое я хочу установить из выбранной строки на сетке данных.

Проблема в том, что при выборе строки поля не заданы;как они устанавливаются?

Просмотр

<Window x:Class="videotheque.View.FilmView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:videotheque.View"
    xmlns:vm="clr-namespace:videotheque.ViewModel"
    mc:Ignorable="d"
    Title="Vos films" Height="480" Width="900">

<Window.DataContext>
    <vm:FilmViewModel/>
</Window.DataContext>

<Grid>
    <DataGrid SelectedItem="{Binding Path=SelectedMovie, Mode=TwoWay}" ItemsSource="{Binding ListFilm, Mode=TwoWay}" CanUserAddRows="False" AutoGenerateColumns="False" Width="499" HorizontalAlignment="Left" Margin="10,0,0,68" Height="371" VerticalAlignment="Bottom">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Titre" Binding="{Binding Titre}" Width="150"/>
            <DataGridTextColumn Header="Durée" Binding="{Binding Duree}"/>
            <DataGridTextColumn Header="Age Min." Binding="{Binding AgeMinimum}"/>
            <DataGridTextColumn Header="Langue" Binding="{Binding LangueMedia}" Width="50"/>
            <DataGridTextColumn Header="Sous titres" Binding="{Binding SousTitres}" Width="60"/>

            <DataGridTemplateColumn Header="Modifier">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button CommandParameter="{Binding Id}" 
                                Command="{Binding Path=DataContext.ModifierLeMediaCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
                            Modifier
                        </Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Supprimer">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button CommandParameter="{Binding Id}"
                                Command="{Binding Path=DataContext.SupprimerLeMediaCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
                            Supprimer
                        </Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

        </DataGrid.Columns>

    </DataGrid>

    <Label Content="Titre :" HorizontalAlignment="Left" Margin="520,11,0,0" VerticalAlignment="Top" Width="39"/>
    <TextBlock Text="{Binding SelectedMovie.Titre, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="568,16,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="0.362,-1.709"/>
    <CheckBox IsChecked="{Binding SelectedMovie.Vu, Mode=TwoWay}" Content="Vu" HorizontalAlignment="Left" Margin="709,17,0,0" VerticalAlignment="Top"/>
    <Label Content="Note :" HorizontalAlignment="Left" Margin="521,42,0,0" VerticalAlignment="Top"/>
    <TextBlock HorizontalAlignment="Left" Margin="568,47,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
    <Label Content="Synopsis :" HorizontalAlignment="Left" Margin="521,82,0,0" VerticalAlignment="Top"/>
    <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="525,113,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="95" Width="209"/>
    <Label Content="Commentaire :" HorizontalAlignment="Left" Margin="519,223,0,0" VerticalAlignment="Top"/>
    <TextBlock HorizontalAlignment="Left" Margin="525,254,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="128" Width="218"/>
    <CheckBox IsChecked="{Binding SelectedMovie.SupportPhysique, Mode=TwoWay}" Content="Support physique" HorizontalAlignment="Left" Margin="709,56,0,0" VerticalAlignment="Top"/>
    <CheckBox IsChecked="{Binding SelectedMovie.SupportNumerique, Mode=TwoWay}" Content="Support numérique" HorizontalAlignment="Left" Margin="709,88,0,0" VerticalAlignment="Top"/>

    <Button Command="{Binding Path=DataContext.AjouterFilmCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
            Content="Ajouter un film" HorizontalAlignment="Left" Margin="10,405,0,0" VerticalAlignment="Top" Width="182"/>

</Grid>

ViewModel (не прошел весь код, есть некоторая командная функция длякнопки, которые работают):

class FilmViewModel 
{
    public ObservableCollection<Media> ListFilm { get; set; }

    private ICommand _modifierLeMediaCommand;

    private ICommand _supprimerLeMedia;

    private Media SelectedMovie;

    public FilmViewModel()
    {
        this.ListFilm = new ObservableCollection<Media>();

        this.LoadData();
    }

    public async void LoadData()
    {
        var context = await DataAccess.VideothequeDbContext.GetCurrent();

        foreach (Media f in context.Medias.Where(m => m.TypeMedia.ToString() == "Film").ToList())
        {
            this.ListFilm.Add(f);
        }

    }
}

И модель:

public class Media
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public DateTime DateSortie { get; set; }

        public TimeSpan Duree { get; set; }

        public string Titre { get; set; }

        public bool Vu { get; set; }

        public int Note { get; set; }

        public string Commentaire { get; set; }

        public string Synopsis { get; set; }

        public ETypeMedia.TypeMedia TypeMedia { get; set; }

        public int AgeMinimum { get; set; }

        public bool SupportPhysique { get; set; }

        public bool SupportNumerique { get; set; }

        public string Image { get; set; }

        public ELangue.Langue LangueVO { get; set; }

        public ELangue.Langue LangueMedia { get; set; }

        public ELangue.Langue SousTitres { get; set; }

        [InverseProperty(nameof(GenreMedia.Media))]
        public List<GenreMedia> Genres { get; set; }

        [InverseProperty(nameof(PersonneMedia.Media))]
        public List<PersonneMedia> Personnes { get; set; }

        [InverseProperty(nameof(Episode.Media))]
        public List<Episode> Episodes { get; set; }

    }

Я слышал о INotifyPropertyChanged, но похоже, что так долго делать с тем, что у меня есть, поэтому я незнаю ...

1 Ответ

1 голос
/ 28 июня 2019

Возьмите под свой контроль, у которого есть привязка с надписью ="{Binding SelectedMovie.Vu, ...}".

Помните, что Binding - это просто отражение в объекте экземпляра того, что определено, что должно перейти к SelectedMovie.Vu.

Свойство SelectedMovie установлено как приватное, и отражение в нем тут же не выполняется (проблема № 1).


Так что давайте сделаем SelectedMovie общедоступным.Это все еще не удается!Даже когда выбор изменяется, привязка не получает данные current .Почему?

Почему, когда элемент управления помещается на экран, он пытается выполнить привязку в то время , свойство которого равно Null.Таким образом, он ничего не показывает.

Когда свойство изменяется, привязка все еще не выполняется, поскольку не получает событие для изменения , поэтому оно может заменить нулевое значение.

Почему?

Свойство не следует INotifyPropertyChanged, поэтому нет события объявляет, что было внесено изменение, поскольку привязка элемента управления будет прослушивать событие изменения для SelectedMovie, но SelectedMovie никогда не объявляет об изменении.

Но возможна третья проблема даже после того, как SelectedMovie сообщает об изменении с помощью INotifyPropertyChanged.Поскольку привязка ищет уведомление о фактическом изменении child от .Vu.

.Vu не объявляет об изменении, потому что оно также не делает InotifyPropertyChanged.Даже если это так ... он не объявляет об изменении, когда установлено SelectedMovie.Откуда он это знает?


Вы можете заставить вашу систему привязки работать, но вам придется делать некоторые дополнительные события уведомления, когда установлен объект верхнего уровня.Вам следует использовать привязку к самому имени DataGrid.Вот пример использования аналогичного ListBox:

Пример В нашем Window или Page или Control я собираюсь настроить некоторые данные в XAML для нашего примера.

Данные

<Window.Resources>
    <model:Orders x:Key="Orders">
        <model:Order CustomerName="Alpha"
                        OrderId="997"
                        InProgress="True" />
        <model:Order CustomerName="Beta"
                        OrderId="998"
                        InProgress="False" />
        <model:Order CustomerName="Omega"
                        OrderId="999"
                        InProgress="True" />
        <model:Order CustomerName="Zeta"
                        OrderId="1000"
                        InProgress="False" />
    </model:Orders>
</Window.Resources>

ListBox

Затем я собираюсь разместить / связать данные в ListBox в которой каждая строка будет TextBox для отображения CustomerName.

<ListBox ItemsSource="{StaticResource Orders}" x:Name="lbOrders">
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type model:Order}">
            <TextBlock Text="{Binding Path=CustomerName}" />
        </DataTemplate>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=InProgress}" Value="True">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.Resources>
</ListBox>

Итак, у нас есть список, в котором отображаются данные:

enter image description here

Показать номер заказа выбранного элемента

Так что теперь мы добавим еще один элемент управления, который будет отображать номер заказа выбранного элемента пользователя.Мы будем связывать, используя ElementName, который будет указывать на свойство зависимостей SelectedItem нашего элемента управления listbox с именем элемента управления, которое мы дали, которое является lbOrders.В этом свойстве оно будет содержать выбранный экземпляр, и мы опустимся до OrderId.

 <Label Content="{Binding SelectedItem.OrderId, ElementName=lbOrders}"/>

Так что, когда мы выбираем Omega, мы получаем «999».

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...