WPF understanding Selector.IsSynchronizedWithCurrentItem
本文关键字:IsSynchronizedWithCurrentItem Selector understanding WPF | 更新日期: 2023-09-27 18:06:00
不知道这是否是特定于inffragistics xamDataGrid的,但这里有一个问题:
inffragistics xamDataGrid公开了一个属性IsSynchronizedWithCurrentItem,根据他们的文档,它将ActiveRecord与实现ICollectionView的数据源的当前项同步。
我有以下MasterDetails窗口,其中包含基于绑定到网格的对象类型的详细信息(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窗口的实例,使用解析为以下dataTemplate的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的背景,并试图在WPF做事情的方式,你会在WinForms。
好消息是,您不需要这样做:Master detail可以使用一个简单的正斜杠来处理。在下面的例子中,看看MainWindow中的绑定。Xaml—正斜杠表示当前选中的项。模型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; }
}
}
MainWindow.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();
}
}
}