我有一个ListView绑定到对象的ObservableCollection。紧接着,我有一堆TextBox和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>
答案 0 :(得分: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; }
}
然后,我将拥有ObservableCollection
个属性,以及与您在班级中拥有的属性一样多的string
个属性;在这种情况下是两个。
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;
}
}
答案 1 :(得分:0)
我最终没有对编辑控件使用数据绑定。相反,我在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;
}
}