将数据从DataGrid绑定到UI组件

时间:2019-06-27 21:15:21

标签: c# wpf mvvm datagrid

我有一个带有数据网格的窗口,该窗口从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 个答案:

答案 0 :(得分:1)

控制您的控件,该控件的绑定内容为="{Binding SelectedMovie.Vu, ...}"

请记住,绑定只是反映到实例对象,该实例对象将被定义为SelectedMovie.Vu

SelectedMovie属性设置为私有,并且在那里的反射失败(问题1)。


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

原因是,当控件放置在屏幕上时,它会尝试绑定当时,其属性为Null。因此它什么也没显示。

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

为什么?

该属性不跟随INotifyPropertyChanged,因此无事件宣布已进行更改,因为控件的绑定将监听SelectedMovie的更改事件,但是{{ 1}}从不宣布更改。

但是即使在SelectedMovie通过使用SelectedMovie报告更改之后,也可能存在第三个问题。因为绑定正在从INotifyPropertyChanged寻找 child 实际更改通知。

.Vu不会宣布更改,因为它也不会.Vu。即使设置为InotifyPropertyChanged,也不会宣布更改。怎么知道?


您可以使绑定系统正常工作,但是在设置了顶级对象时,您将不得不执行一些额外的通知事件。您应该使用的是对命名的SelectedMovie本身的绑定。这是使用类似DataGrid的示例:

示例 在我们的ListBoxWindowPage中,我将在XAML中为我们的示例设置一些数据。

数据

Control

列表框

然后,我将数据托管/绑定到<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,以显示TextBox

CustomerName

所以我们有一个显示数据的列表框:

enter image description here

显示所选商品的订单号

因此,现在我们在其下添加另一个控件,该控件将显示用户所选项目的订单号。我们将使用<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> 进行绑定,该指向我们的列表框控件的ElementName依赖属性,我们给定的控件名称为SelectedItem。在该属性上,它将保存选定的实例,我们将向下钻取到lbOrders

OrderId

因此,当我们选择 <Label Content="{Binding SelectedItem.OrderId, ElementName=lbOrders}"/> 时,将显示“ 999”。

enter image description here

相关问题