C# 将数据从datagrid绑定到ui组件

C# 将数据从datagrid绑定到ui组件,c#,wpf,mvvm,datagrid,C#,Wpf,Mvvm,Datagrid,我有一个窗口,其中有一个datagrid,它从一个ObservaleCollection获取他的项目,我想从datagrid上的选定行设置一些字段 问题是,当我选择一行时,这些字段没有设置;它们是如何被设置的 查看 <Window x:Class="videotheque.View.FilmView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schem

我有一个窗口,其中有一个datagrid,它从一个
ObservaleCollection
获取他的项目,我想从datagrid上的选定行设置一些字段

问题是,当我选择一行时,这些字段没有设置;它们是如何被设置的

查看

<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(没有通过所有代码,只有一些按钮的命令功能可用):

类FilmViewModel
{
公共可观察收集列表胶片{get;set;}
专用ICommand_modifierLeMediaCommand;
私人ICommand_SupplierMedia;
私人媒体选择Movie;
公共FilmViewModel()
{
this.ListFilm=新的ObservableCollection();
这是LoadData();
}
公共异步void LoadData()
{
var context=await DataAccess.VideothequeDbContext.GetCurrent();
foreach(context.Medias.Where(m=>m.TypeMedia.ToString()==“Film”).ToList()中的媒体f)
{
本.列表胶片.添加(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; }

    }
公共类媒体
{
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
公共日期时间日期出勤{get;set;}
公共时间间隔{get;set;}
公共字符串标题{get;set;}
公共bool Vu{get;set;}
公共int注释{get;set;}
公共字符串注释{get;set;}
公共字符串摘要{get;set;}
public ETypeMedia.TypeMedia TypeMedia{get;set;}
公共整数最小值{get;set;}
公共布尔支持Physique{get;set;}
公共bool支持numerique{get;set;}
公共字符串图像{get;set;}
public ELangue.Langue LangueVO{get;set;}
公共语言语言语言媒体{get;set;}
public ELangue.Langue soustires{get;set;}
[反向属性(名称(GenreMedia.Media))]
公共列表类型{get;set;}
[反向属性(名称(personeMedia.Media))]
公共列表人员{get;set;}
[InverseProperty(名称(插曲、媒体))]
公共列表集{get;set;}
}

我确实听说过INotifyPropertyChanged,但它似乎与我所拥有的东西有关太久了,所以我不知道……

控制你的控件,它有一个绑定,上面写着
=“{binding SelectedMovie.Vu,…}”

请记住,绑定只不过是实例对象中定义的内容的反射,该对象将转到
SelectedMovie.Vu

SelectedMovie
属性设置为private,反射到该属性的操作将立即失败(问题1)


因此,让我们将
SelectedMovie
公开。它仍然失败!即使选择更改,绑定也不会获取当前数据。为什么?

原因是当控件放在屏幕上时,它会尝试绑定,该绑定的属性为
Null
。所以它没有显示任何东西

当属性更改时,绑定仍然失败,因为它没有收到更改事件,因此可以替换空值

为什么?

属性不遵循
INotifyPropertyChanged
,因此没有事件宣布已进行更改,因为控件的绑定将侦听
SelectedMovie
的更改事件,但
SelectedMovie
从不宣布更改

但即使在
SelectedMovie
使用
INotifyPropertyChanged
报告更改后,也可能存在第三个问题。因为绑定正在从
.Vu
查找子级实际更改通知

.Vu
不会宣布更改,因为它也不会执行
InotifyPropertyChanged
。即使有,当设置了
SelectedMovie
时,它也不会宣布更改。它怎么知道


您可以使绑定系统正常工作,但在设置顶级对象时,必须执行一些额外的通知事件。您应该使用到命名的
DataGrid
本身的绑定。下面是一个使用类似的
列表框的示例:

示例 在我们的
窗口
页面
控件
中,我将在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>
因此,我们有一个列表框显示数据:

显示所选项目的订单号

现在我们在它下面添加另一个控件,它将显示用户所选项目的订单号。我们将使用
ElementName
进行绑定,它将指向listbox控件的
SelectedItem
依赖性属性,并使用我们给定的控件名
lbOrders
。在该属性上,它将保存所选实例,我们将深入到
OrderId

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

因此,当我们选择
Omega
时,会显示“999”


您在视图中绑定到的SelectedMovie是视图模型中的专用字段。它必须是公共财产。
<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>
 <Label Content="{Binding SelectedItem.OrderId, ElementName=lbOrders}"/>