【问题标题】:Binding data from datagrid to ui components将数据从数据网格绑定到 ui 组件
【发布时间】:2019-06-27 21:15:21
【问题描述】:

我有一个带有数据网格的窗口,它从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,但它似乎与我所拥有的东西有关,所以我不知道......

【问题讨论】:

  • 您在视图中绑定的 SelectedMovie 是视图模型中的私有字段。它必须是公共财产。

标签: c# wpf mvvm datagrid


【解决方案1】:

控制具有="{Binding SelectedMovie.Vu, ...}" 绑定的控件。

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

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


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

原因是当控件被放置在屏幕上时,它会尝试绑定当时,其属性为Null。所以它什么都不显示。

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

为什么?

属性不跟随INotifyPropertyChanged,所以没有事件宣布发生了变化,因为控件的绑定将监听SelectedMovie的变化事件,但SelectedMovie从不宣布改变。

但即使在SelectedMovie 使用INotifyPropertyChanged 报告更改后,也可能存在第三个问题。因为绑定正在寻找来自.Vuchild 实际更改通知。

.Vu 不会宣布更改,因为它也不会执行InotifyPropertyChanged。即使它确实......它不会在设置SelectedMovie 时宣布更改。它怎么知道?


你可以让你的绑定系统工作,但是当顶层对象被设置时你将不得不做一些额外的通知事件。您应该使用的是绑定到已命名的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 中托管/绑定数据,其中每一行都是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>

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

显示所选商品的订单号

所以现在我们在它下面添加另一个控件,它将显示用户所选商品的订单号。我们将使用ElementName 绑定,它将指向我们的列表框控件的SelectedItem 依赖属性,我们给定的控件名称为lbOrders。在该属性上,它将保存选定的实例,我们将向下钻取到 OrderId

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

所以当我们选择Omega 时,我们会看到“999”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多