c# - WPF 理解 Selector.IsSynchronizedWithCurrentItem

标签 c# wpf xaml selector xamdatagrid

不知道这是否特定于 Infragistics xamDataGrid,但问题是:

Infragistics xamDataGrid 公开了一个属性 IsSynchronizedWithCurrentItem,根据他们的文档,该属性将 ActiveRecord 与实现 ICollectionView 的数据源的当前项同步。

我有以下 MasterDetails 窗口,其中包含基于绑定(bind)到网格的对象类型的详细信息 (ContentControl) 内容:

 <DockPanel Name="dockPanel" LastChildFill="True">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="5" MaxHeight="5"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <igDP:XamDataGrid 
                Name="dataGrid"                                  
                IsSynchronizedWithCurrentItem="True"
                SelectedItemsChanged="dataGrid_SelectedItemsChanged">                    
            </igDP:XamDataGrid>
            <GridSplitter              
                Style="{StaticResource blueHrizontalGridSplitter}"
                Grid.Row="1" Grid.ColumnSpan="2"              
                BorderThickness="1" Margin="1,0"
                HorizontalAlignment="Stretch"   />            

            <ContentControl Grid.Row="2" Name="contentControl" />

        </Grid>
    </DockPanel>

在后面的代码中,我试图在网格数据源的当前项与 MasterDetailsWindow 的构造函数中的详细信息控件的 DataContext 之间建立链接,如下所示:

 if (detailsControl != null)
            {
                var fwDControl = detailsControl as FrameworkElement;
                if (fwDControl != null)
                {
                    var b = new Binding() { ElementName = "dataGrid", Path = new PropertyPath("DataSource") };
                    fwDControl.SetBinding(DataContextProperty, b);
                }

                contentControl.Content = detailsControl;                     
            }
            else
            {
                var b = new Binding() { ElementName = "dataGrid", Path = new PropertyPath("DataSource") };
                contentControl.SetBinding(ContentProperty, b);

                b = new Binding("DataDetailsTemplate");
                contentControl.SetBinding(ContentTemplateProperty, b);
            }  

在构建 MasterDetails 的实例时,调用者需要提供一个 detailsControl 对象或一个表示 DataTemplate URL 的字符串。如果提供了 detailsControl,我将执行检查 details 是否不为空的代码。否则,我假定提供了 DataDetailsTemplate。

我会怀疑我在这里的想法,但如果我构造一个 MasterDetails 窗口的实例,并使用解析为以下数据模板的 URL:

<DataTemplate x:Key="LogDetailsTemplate">                 
        <Grid Margin="5,5,5,0">
            <TextBox Text="{Binding Message}" TextWrapping="WrapWithOverflow"/>            
        </Grid>     
    </DataTemplate>

在网格中选择一个项目,在 TextBox 中显示所选对象的相应 Message 属性。

但是,如果我提供一个派生自 UserControl 的自定义 detailsControl 对象,则在网格中选择一个项目不会导致更改我的 detailsControl 的 DataContext。这是为什么?

TIA。

最佳答案

哇哦!!!!!我可能是错的,但看起来您有 WinForms 背景,并且正在尝试按照您在 WinForms 中的方式在 WPF 中做事。

好消息是,您不必:可以使用简单的正斜杠处理主细节。在下面的示例中,查看 MainWindow.xaml 中的绑定(bind) - 正斜杠表示当前选定的项目。

模型

public class Country
{
    public string Name { get; set; }
    public int Population { get; set; }
}

public class Continent
{
    public string Name { get; set; }
    public int Area { get; set; }
    public IList<Country> Countries { get; set; }
}

查看模型

    public class MainViewModel
    {
        private ObservableCollection<ContinentViewModel> _continents;

        public ObservableCollection<ContinentViewModel> Continents
        {
            get { return _continents; }
            set
            {
            _continents = value;
            ContinentView = new ListCollectionView(_continents);
            ContinentView.CurrentChanged += (sender, agrs) => CurrentContinent = ContinentView.CurrentItem as ContinentViewModel;
        }
    }
    public ListCollectionView ContinentView {get; private set;}

    /// <summary>
    /// Use this to determine the current item in the list 
    /// if not willing to use \ notation in the binding.
    /// </summary>
    public ContinentViewModel CurrentContinent { get; set; }
}

public class ContinentViewModel
{
    private Continent _model;

    public Continent Model
    {
        get { return _model; }
        set
        {
            _model = value;
            Countries = _model.Countries
                .Select(p => new CountryViewModel { Model = p })
                .ToList();
        }
    }

    public string Name
    {
        get { return Model.Name; }
    }

    public int Area
    {
        get { return Model.Area; }
    }

    public List<CountryViewModel> Countries { get; private set; }
}

public class CountryViewModel
{
    public Country Model { get; set; }

    public string Name
    {
        get { return Model.Name; }
    }

    public int Population 
    {
        get { return Model.Population; }
    }
}

主窗口.xaml

<Window x:Class="XamDataGridMasterDetail.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Views="clr-namespace:XamDataGridMasterDetail.Views"
        xmlns:igDP="http://infragistics.com/DataPresenter"
        Title="MainWindow">
    <Grid>
        <StackPanel Orientation="Vertical">

            <!-- Continent list -->
            <igDP:XamDataGrid HorizontalAlignment="Left"
                              Margin="10,10,0,0"
                              Name="xamDataGrid1"
                              Height="300"
                              VerticalAlignment="Top"
                              DataSource="{Binding ContinentView}"
                              IsSynchronizedWithCurrentItem="True">
                <igDP:XamDataGrid.FieldSettings>
                    <igDP:FieldSettings  CellClickAction="SelectRecord" />
                </igDP:XamDataGrid.FieldSettings>
                <igDP:XamDataGrid.FieldLayouts>
                    <igDP:FieldLayout>
                        <igDP:FieldLayout.Settings>
                            <igDP:FieldLayoutSettings AutoGenerateFields="False" />
                        </igDP:FieldLayout.Settings>
                        <igDP:FieldLayout.Fields>
                            <igDP:Field Name="Name"
                                        Label="Name" />
                            <igDP:Field Name="Area"
                                        Label="Area" />
                            <igDP:UnboundField Label="# Countries"
                                               Binding="{Binding Countries.Count}" />
                        </igDP:FieldLayout.Fields>
                    </igDP:FieldLayout>
                </igDP:XamDataGrid.FieldLayouts>
            </igDP:XamDataGrid>

            <!-- Continent detail -->
            <ListBox ItemsSource="{Binding ContinentView/Countries}"
                     DisplayMemberPath="Name"
                     IsSynchronizedWithCurrentItem="True"
                     Height="200" />

            <!-- Country detail -->
            <StackPanel Orientation="Horizontal">
                <Label Content="Name: " />
                <TextBlock Text="{Binding ContinentView/Countries/Name}" />
                <Label Content="Population: " />
                <TextBlock Text="{Binding ContinentView/Countries/Population}" />
            </StackPanel>



        </StackPanel>
    </Grid>
</Window>

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using XamDataGridMasterDetail.ViewModels;
using System.Collections.ObjectModel;
using XamDataGridMasterDetail.Model;

namespace XamDataGridMasterDetail
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
        {
            base.OnSessionEnding(e);
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            var view = new MainWindow();
            var vm = new MainViewModel();
            vm.Continents = new ObservableCollection<ContinentViewModel>();
            vm.Continents.Add(new ContinentViewModel
            {
                Model = new Continent
                {
                    Name = "Australasia",
                    Area = 100000,
                    Countries = new[] 
                    {
                        new Country 
                        {
                            Name="Australia",
                            Population=100
                        },
                        new Country
                        {
                            Name="New Zealand",
                            Population=200
                        }
                    }
                }
            });
            vm.Continents.Add(new ContinentViewModel
            {
                Model = new Continent
                {
                    Name = "Europe",
                    Area = 1000000,
                    Countries = new[] 
                    {
                        new Country 
                        {
                            Name="UK",
                            Population=70000000
                        },
                        new Country
                        {
                            Name="France",
                            Population=50000000
                        },
                        new Country
                        {
                            Name="Germany",
                            Population=75000000
                        }
                    }
                }
            });
            view.DataContext = vm;
            view.Show();
        }

    }
}

关于c# - WPF 理解 Selector.IsSynchronizedWithCurrentItem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7081641/

相关文章:

c# - 在 Spy++ 中,控件名称的值是多少?

windows - 使用 UIElement 创建 Cordova UWP 插件

wpf - 如何使数据网格的宽度自动适应父控件的宽度

c# - 查看EF4生成的查询?

c# - XNA 的高 CPU 使用率

c# - 如何在 C# 中使用 'union' 2 个或更多数据表?

wpf mvvm .. 访问 View 模型中的 View 元素

wpf - 导致属性触发切换复选框 WPF DataGrid

wpf - wpf切换按钮: Display text along with image as content

wpf - 同时使用 ValidationAdornerSite 和 ErrorTemplate