0

我正在使用 anXceed PropertyGrid来显示各种对象的属性。在大多数情况下,这很简单。我只是将SelectedObject属性设置为适当的对象。

但是,我有一种情况,其中一个对象属性是对来自不同类的集合的另一个对象的引用。我在这里创建了一个简化示例,用于演示和测试目的。在这个例子中,Person对象有一个City属性,它是CityModel类的一个实例。因此,对于任何给定Person的,用户应该能够从cities集合中选择他们的居住城市。人和城市的集合是——或者至少是真实的——动态的和用户可以改变的。

ComboBox我可以使用 an填充 a ,但在引用该集合EditorTemplate时遇到问题。cities

如果试图将 定义SourceStaticResource,我没有得到预期的行为。Microsoft 的此操作指南显示ObservableCollection( People) 被定义为 aResource并随后在数据绑定中被引用为 a StaticResource。当我尝试做同样的事情时,Visual Studio 显然期望Resource定义是一个类而不是类实例。它为我提供了CityModelor选项PersonModel,但不是cities我认为应该根据操作方法在此处指定的集合。

Intellisense 显示数据源定义的可用选项

如果Source不指向集合,我不确定在绑定中如何以及在何处指定它,因为(再次基于 Intellisense)它不能进入Path​​ .

在不使用 aStaticResource的情况下,我可以执行以下任一操作,这两者都会导致空白列表:

ItemsSource="{Binding Source=DataContext.cities, Path=Name}"

ItemsSource="{Binding Source=cities, Path=Name}"

或者这样,导致文本字符串“城市”被用作源:

ItemsSource="{Binding Source=cities}"

cities在下面的代码中,我可以通过在类中复制集合来获得所需的结果Person,这将其暴露给 ,ComboBox而不必指定 a Source,但这在很大程度上是一种解决方法。

<Grid>
    <StackPanel Orientation="Vertical">
        <TextBlock Padding="0,10,0,5">People:</TextBlock>
        <ListBox Name="listPeople" ItemsSource="{Binding people}" DisplayMemberPath="FirstName" SelectionChanged="listBox_SelectionChanged" />
        <TextBlock Padding="0,10,0,5">Cities:</TextBlock>
        <ListBox Name="listCities" ItemsSource="{Binding cities}" DisplayMemberPath="Name" SelectionChanged="listBox_SelectionChanged" />
        <TextBlock Padding="0,10,0,5">Properties:</TextBlock>
        <xctk:PropertyGrid x:Name="MyPropertyGrid">
            <xctk:PropertyGrid.EditorDefinitions>
                <xctk:EditorTemplateDefinition TargetProperties="City">
                    <xctk:EditorTemplateDefinition.EditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Instance.citiesList}" SelectedValue="{Binding Instance.City}" />
                        </DataTemplate>
                    </xctk:EditorTemplateDefinition.EditingTemplate>
                </xctk:EditorTemplateDefinition>
            </xctk:PropertyGrid.EditorDefinitions>
        </xctk:PropertyGrid>
    </StackPanel>
</Grid>

public partial class MainWindow : Window
{
    
    public ObservableCollection<CityModel> cities { get; set; } = new ObservableCollection<CityModel>();
    public ObservableCollection<PersonModel> people { get; set; } = new ObservableCollection<PersonModel>();
    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;

        // Create some cities...
        CityModel tokyo = new CityModel() { Id = 0, Name = "Tokyo" };
        CityModel london = new CityModel() { Id = 1, Name = "London" };
        CityModel buenosAires = new CityModel() { Id = 2, Name = "Buenos Aries" };
        cities = new ObservableCollection<CityModel>() { tokyo, london, buenosAires };

        // Create some people...
        PersonModel juan = new PersonModel() { FirstName = "Juan", LastName = "Garcia", City = buenosAires };
        PersonModel bridget = new PersonModel() { FirstName = "Bridget", LastName = "Jones", City = london };
        PersonModel aoife = new PersonModel() { FirstName = "Aoife", LastName = "O'Connor", City = tokyo };
        people = new ObservableCollection<PersonModel>() { juan, bridget, aoife };

        // Workaround in order to expose list of cities along with Person properties...
        foreach (PersonModel person in people) { person.citiesList = cities; }

    }

    private void listBox_SelectionChanged(object sender, RoutedEventArgs e)
    {
        ListBox listBox = sender as ListBox;
        MyPropertyGrid.SelectedObject = listBox.SelectedItem;
    }
}

public class PersonModel
{
    public string FirstName { get; set; } = "";

    public string LastName { get; set; } = "";

    public CityModel City { get; set; } = new CityModel();

    // Workaround in order to expose list of cities along with Person properties...
    public ObservableCollection<CityModel> citiesList { get; set; } = new ObservableCollection<CityModel>();
}

public class CityModel
{
    public int Id { get; set; } = 0;
    public string Name { get; set; } = "";
    public override string ToString() { return Name; }
}
4

0 回答 0