【问题标题】:Two-way link to the properties of all SelectedItems of a ListView?双向链接到 ListView 的所有 SelectedItems 的属性?
【发布时间】:2019-10-08 05:57:24
【问题描述】:

我有一个 ListView 绑定到对象的 ObservableCollection。在这旁边,我有一堆 TextBoxes 和 ComboBoxes,它们被 TwoWay 绑定到该 ListView 的 SelectedItem 的属性。我的 ListView 中的项目具有 INotifyPropertyChanged。这样用户就可以从 ListView 中选择一个项目并编辑它的属性。

但是编辑大量项目需要很长时间,所以我希望用户能够选择多个项目并使用 ListView 旁边的控件一次编辑所有选定项目的属性。

我已经尝试将 DataContext 更改为 ListView 的 SelectedItems 属性,但没有成功。

谁能告诉我该怎么做?

编辑: 为了澄清,当用户选择多个项目时,我希望 ListView 旁边的编辑控件不显示任何内容,然后只有当用户更改这些控件中的某些内容时,更改才会转到所有 SelectedItems 并且更改在 TextBox 中保持可见或 ComboBox,因为这样该属性在所有 SelectedItems 中都是相同的。

<StackPanel x:Name="EditPanel" Grid.Row="0" Grid.RowSpan="2" DataContext="{Binding SelectedItem, ElementName=LayersList}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CanVerticallyScroll="True">
    <TextBlock FontSize="14" HorizontalAlignment="Stretch" Foreground="#FFD6D6D6" Margin="0,10,0,0"><Run Text="Name:"/></TextBlock>
    <TextBox x:Name="SelectedNameBox" HorizontalAlignment="Stretch" TextWrapping="NoWrap" Foreground="#FFD6D6D6" Text="{Binding Name, Mode=TwoWay}"/>
    <TextBlock FontSize="14" HorizontalAlignment="Stretch" Foreground="#FFD6D6D6" Margin="0,10,0,0"><Run Text="Hitsound info:"/></TextBlock>
    <ComboBox x:Name="SelectedSampleSetBox" Margin="0,10,0,0" HorizontalAlignment="Stretch" Text="{Binding SampleSetString, Mode=TwoWay}" Cursor="Hand">
        <ComboBoxItem Content="Normal" HorizontalAlignment="Left" Cursor="Hand"/>
        <ComboBoxItem Content="Soft" HorizontalAlignment="Left" Cursor="Hand"/>
        <ComboBoxItem Content="Drum" HorizontalAlignment="Left" Cursor="Hand"/>
    </ComboBox>
    <ComboBox x:Name="SelectedHitsoundBox" Margin="0,10,0,0" HorizontalAlignment="Stretch" Text="{Binding HitsoundString, Mode=TwoWay}" Cursor="Hand">
        <ComboBoxItem Content="Normal" HorizontalAlignment="Left" Cursor="Hand"/>
        <ComboBoxItem Content="Whistle" HorizontalAlignment="Left" Cursor="Hand"/>
        <ComboBoxItem Content="Finish" HorizontalAlignment="Left" Cursor="Hand"/>
        <ComboBoxItem Content="Clap" HorizontalAlignment="Left" Cursor="Hand"/>
    </ComboBox>
    ...
</StackPanel>

【问题讨论】:

  • 当您选择多个项目时,您希望相关数据出现在哪里?由于您不知道用户会选择多少,因此您希望动态添加多个控件。
  • 一种选择是在可编辑的 DataGrid(甚至是自定义的 ListView)中显示列表,以便您可以就地编辑项目。
  • @Sach 我编辑了这个问题以便进一步澄清。
  • 更新了答案。

标签: c# wpf xaml listview data-binding


【解决方案1】:

正如您所描述的问题,您似乎还没有考虑到这一点。

如果您有一个列表,以及一堆控件,它显示所选项目属性,您希望在选择多个项目时要显示的属性数据?例如,如果你有一个像这样的Person 类:

public class Person
{
    public string Name { get; set; }
    public string City { get; set; }
    public int Age { get; set; }
}

当用户从列表中选择两个不同的Person 实例时,您是否希望分配给Name 属性的文本框显示所有选定的名称?如果没有,如果您希望它们在不同的文本框中,那么您必须动态创建与用户选择的项目一样多的文本框。我觉得其中任何一个都可能不是理想的解决方案。

这是另一种解决方案;您在DataGrid 中显示您的数据。 我在这里使用了最简单的DataGrid,启用了AutoGeneratingColumns

<DataGrid Grid.Row="0" Margin="4"
          Name="DataGridPersons"
          AutoGenerateColumns="True"
          ItemsSource="{Binding Persons}"/>

然后,在您的代码背后(理想情况下,您将使用 MVVM 模式,在这种情况下,在您的 ViewModel 中)您只需填充您的数据列表。

public ObservableCollection<Person> Persons { get; set; }

public MainWindow()
{
    InitializeComponent();

    Persons = new ObservableCollection<Person>
    {
        new Person() { Name = "Jane", City = "NY", Age = 23 },
        new Person() { Name = "Chelsea", City = "LA", Age = 27 },
        new Person() { Name = "Chris", City = "Chicago", Age = 25 }
    };

    DataContext = this;
}

默认情况下,DataGrid 是可编辑的,并且会记录您所做的更改。

可编辑DataGrid:


编辑:

在 OP 的编辑问题之后,这是一个新的答案。

在这种情况下,我会摆脱 SelectedItem,而是让不同的 string 属性对应于您的类对象中的每个属性。

假设您的 Person 课程是这样的:

public class Person
{
    public string Name { get; set; }
    public string City { get; set; }
}

然后,我将拥有 ObservableCollectionstring 属性,就像您在班级中拥有的属性一样;在这种情况下有两个。

public ObservableCollection<Person> Persons { get; set; }

private string _editName = null;
public string EditName
{
    get { return _editName; }
    set
    {
        _editName = value;
        OnPropertyChanged("EditName");
    }
}

private string _editCity = null;
public string EditCity
{
    get { return _editCity; }
    set
    {
        _editCity = value;
        OnPropertyChanged("EditCity");
    }
}

然后我会将文本框绑定到这些属性:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <ListBox Grid.Column="0" Grid.Row="0" Grid.RowSpan="3"
             Margin="8" Name="ItemListBox"
             ItemsSource="{Binding Persons}"
             DisplayMemberPath="Name"/>

    <TextBox Grid.Column="1" Grid.Row="0"
             Margin="8" Name="TxtName"
             TextChanged="TxtName_TextChanged"
             Text="{Binding EditName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBox Grid.Column="1" Grid.Row="1"
             Margin="8" Name="TxtCity"
             TextChanged="TxtCity_TextChanged"
             Text="{Binding EditCity, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

在每个文本框的TextChanged 事件中,我会更新您的ObservableCollection

private void TxtName_TextChanged(object sender, TextChangedEventArgs e)
{
    foreach (var person in Persons)
    {
        person.Name = EditName;
    }
}

private void TxtCity_TextChanged(object sender, TextChangedEventArgs e)
{
    foreach (var person in Persons)
    {
        person.City = EditCity;
    }
}

【讨论】:

    【解决方案2】:

    我最终没有为编辑控件使用数据绑定。相反,我在 ListView 的 SelectionChangedEvent 上显式更新它们。在那里,它还描述了如何一次显示多个选定项目的逻辑。

    suppressEvents = true;
    
    if (selectedLayers.TrueForAll(o => o.Name == selectedLayer.Name)) {
        SelectedNameBox.Text = selectedLayer.Name;
    } else {
        SelectedNameBox.Text = "";
    }
    ...
    
    suppressEvents = false;
    

    然后编辑控件的ChangedEvents更新所有的SelectedItems。

    private void SelectedNameBox_TextChanged(object sender, TextChangedEventArgs e) {
        if (suppressEvents) return;
    
        string t = (sender as TextBox).Text;
        foreach (HitsoundLayer hitsoundLayer in LayersList.SelectedItems) {
            hitsoundLayer.Name = t;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 2015-07-24
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2015-09-24
      • 1970-01-01
      相关资源
      最近更新 更多