c# - 将数据从数据网格绑定(bind)到 ui 组件

标签 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 ,但我所拥有的东西看起来很长,所以我不知道......

最佳答案

控制它有一个绑定(bind)说 ="{Binding SelectedMovie.Vu, ...}" .

请记住,绑定(bind)是 只是反射(reflect)到实例对象什么是定义的去SelectedMovie.Vu .
SelectedMovie属性设置为私有(private),并且反射在那里失败(问题#1)。

所以让我们制作SelectedMovie上市。它仍然失败!即使选择更改,绑定(bind)也不会得到 当前数据。为什么?

原因是当控件放在屏幕上时它会尝试绑定(bind) 那时属性是Null .所以它没有显示任何东西。

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

为什么?

属性不跟随INotifyPropertyChanged所以没有事件宣布已进行更改,因为控件的绑定(bind)将监听 SelectedMovie 的更改事件, 但是 SelectedMovie从不宣布改变。

但是即使在 SelectedMovie 之后也可能存在第三个问题。使用 INotifyPropertyChanged 报告更改.因为绑定(bind)正在寻找来自 .Vu 的子实际更改通知.
.Vu不宣布更改,因为它也不做 InotifyPropertyChanged .即使它确实...它不会在 SelectedMovie 时宣布更改已设置。它怎么会知道?

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

示例
在我们的 WindowPageControl我将为我们的示例在 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 中托管/绑定(bind)数据其中每一行都是 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 进行绑定(bind)这将指向我们的列表框控件的SelectedItem具有我们给定的控件名称的依赖属性,即 lbOrders .在该属性上,它将保存选定的实例,我们将向下钻取到 OrderId .
 <Label Content="{Binding SelectedItem.OrderId, ElementName=lbOrders}"/>

所以当我们选择Omega我们得到“999”显示。

enter image description here

关于c# - 将数据从数据网格绑定(bind)到 ui 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56798554/

相关文章:

c# - 在 WPF 应用程序 c# 或 vb.net 中读取 jpg、调整大小、另存为 png

wpf - 属性名称不适用于我的数据网格列绑定(bind)

c# - MVVM:绑定(bind)到模型,同时使模型与服务器版本保持同步

wpf - 如何访问 WPF App 和 ClassLibrary 的成员,反之亦然

c# - 如何根据父 div 中的符号删除它?

c# - 如何更快地加载/卸载图 block block (C#)

wpf - 如何防止 WPF 编辑框在编程式 SelectAll 上滚动结束?

wpf - 启动WPF应用程序时出现问题

c# - 尝试在 LINQ 循环内进行 catch

c# - 字段突然增加