0

我正在尝试使用ListBox.Items.Remove从列表框中删除动态创建的按钮,但我不断收到错误消息“在使用 ItemsSource 时操作无效。改为使用 ItemsControl.ItemsSource 访问和修改元素。” 问题是,ItemsControl.ItemsSource在我的代码中不是一个有效的选项。

代码有点破败:我有一个包含 ListBox 和“添加”和“删除”按钮的 MainWindow。添加按钮会将您带到一个窗口,您可以在其中输入名字和姓氏。单击“完成”将新创建的配置文件的按钮添加到列表框(您可以通过单击所述按钮访问配置文件)。除了名字和姓氏被绑定到那里的标签之外,我没有将配置文件代码包含为空。

我将如何访问/修改按钮/配置文件以删除它们?我知道这与数据绑定有关,但我对如何删除该项目感到非常困惑。

任何帮助将非常感激。我在下面包含了 MainWindow 和 ProfileCreator 代码。

<Window x:Class="SavingButtons.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <DataTemplate x:Key="UserTemplate">
        <StackPanel Orientation="Horizontal">
            <Button Name="TestAddButton" Click="TestAddButton_Clicked" Content="{Binding FirstName}" Width="100" Height="40"></Button> 
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<Grid>
    <Button Name="AddProfileButton" Content="Add Profile" HorizontalAlignment="Left" Margin="22,29,0,0" VerticalAlignment="Top" Width="75" Click="AddProfileButton_Click"/>
    <ListBox Name="ButtonHoldersListbox" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" ItemTemplate="{StaticResource UserTemplate}" HorizontalAlignment="Left" Height="202" Margin="22,69,0,0" VerticalAlignment="Top" Width="183" />
    <Button Name="DeleteUserButton" Click="DeleteUserButton_Click" Content="Delete User" HorizontalAlignment="Left" Margin="246,69,0,0" VerticalAlignment="Top" Width="105"/>
</Grid>

namespace SavingButtons
{
public partial class MainWindow : Window
{
    NewProfile np;
    public int buttonNumberID;
    public MainWindow()
    {
        InitializeComponent();
        np = new NewProfile(this);
    }

    private void AddProfileButton_Click(object sender, RoutedEventArgs e)
    {
        np.Show();
    }
    //adds button to listbox
    internal void TestAddButton_Clicked(object sender, RoutedEventArgs e)
    {
        Button cmd = (Button)sender;
        if (cmd.DataContext is User)
        {
            //Profile is where the finished information is displayed//
            Profile pro = new Profile();
            pro.DataContext = cmd.DataContext;
            pro.Show();
        }
    }
    //this is where confusion ensues
    private void DeleteUserButton_Click(object sender, RoutedEventArgs e)
    {
        //error occurs here
        ButtonHoldersListbox.Items.Remove(ButtonHoldersListbox.SelectedItem);

    }
}
}

个人资料创建者:

<Window x:Class="SavingButtons.NewProfile"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="NewProfile" Height="300" Width="500">
<Grid>
    <Label Content="FirstName" HorizontalAlignment="Left" Margin="64,44,0,0" VerticalAlignment="Top"/>
    <Label Content="LastName" HorizontalAlignment="Left" Margin="64,97,0,0" VerticalAlignment="Top"/>
    <Button Name="UploadImageButton" Click="UploadImageButton_Click" Content="Upload Image" HorizontalAlignment="Left" Margin="64,146,0,0" VerticalAlignment="Top" Width="75"/>

    <TextBox Name="FirstNameTextBox" HorizontalAlignment="Left" Height="23" Margin="126,47,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
    <TextBox Name="LastNameTextBox" HorizontalAlignment="Left" Height="23" Margin="126,99,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
    <Image Name="imgPhoto" HorizontalAlignment="Left" Height="100" Margin="173,146,0,0" VerticalAlignment="Top" Width="100"/>

    <Button Name="ProfileFinishedLaunch" Content="Done" HorizontalAlignment="Left" Margin="360,232,0,0" VerticalAlignment="Top" Width="75" Click="ProfileFinishedLaunch_Click"/>
</Grid>

 namespace SavingButtons
{
public partial class NewProfile : Window
{
    public ObservableCollection<User> ProfileList;
    public MainWindow mMain;

    public NewProfile(MainWindow main)
    {
        InitializeComponent();
        ProfileList = new ObservableCollection<User>();
        mMain = main;
    }

    //loads image
    private void UploadImageButton_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog op = new OpenFileDialog();
        op.Title = "Select a picture";
        op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
            "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
            "Portable Network Graphic (*.png)|*.png";
        if (op.ShowDialog() == true)
        {
            imgPhoto.Source = new BitmapImage(new System.Uri(op.FileName));
        }
    }
    //creates a new user out of all the info, inserts new user into the collection, adds new button
    private void ProfileFinishedLaunch_Click(object sender, RoutedEventArgs e)
    {
        mMain.buttonNumberID++;
        ProfileList.Add(new User { FirstName = FirstNameTextBox.Text, LastName = LastNameTextBox.Text, imgPhoto = imgPhoto.Source });

        mMain.ButtonHoldersListbox.DataContext = ProfileList; 

        mMain.Show();
        this.Hide();
    }
4

3 回答 3

1

You are setting yourListbox` 到其他窗口属性,您每次添加新项目后都这样做。

发生错误,因为列表框项是通过绑定到ItemsSource属性设置的,在这种情况下ListBox.Items是只读的,因此您不能直接删除或添加项。

而不是你现在拥有的,ObservableCollection<User>向你的类添加一个属性MainWindow并将 绑定ListBox到这个属性。在NewProfile窗口中,您需要将新的用户项添加到此集合中。删除操作将用于从该集合中删除项目(实际上是 senders DataContext

public partial class MainWindow : Window
{
    public ObservableCollection<User> Profiles {get; set;}

    //...

    private void DeleteUserButton_Click(object sender, RoutedEventArgs e)
    {
      var removable = ButtonHoldersListbox.SelectedItem as User;
      if(removable != null)
        Profiles.Remove(removable);
    }
}


<ListBox Name="ButtonHoldersListbox" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Profiles}" ItemTemplate="{StaticResource UserTemplate}" HorizontalAlignment="Left" Height="202" Margin="22,69,0,0" VerticalAlignment="Top" Width="183" />


public partial class NewProfile : Window
{

//creates a new user out of all the info, inserts new user into the collection, adds new button
private void ProfileFinishedLaunch_Click(object sender, RoutedEventArgs e)
{
    mMain.buttonNumberID++;
    var newUser = new User { FirstName = FirstNameTextBox.Text, LastName = LastNameTextBox.Text, imgPhoto = imgPhoto.Source };

    mMain.Profiles.Add(newUser); 

    //Don't set the listbox.DataContext here

    mMain.Show();
    this.Hide();
}
于 2013-09-02T08:00:10.760 回答
0

感谢 Miklos,我确实解决了我的问题,但是,绑定仍然很混乱。主要是:ListBox怎么知道绑定ObservableCollection ProfileList?在 Mikalos 版本中,他将 ObservableCollection 显式绑定到 XAML 中的 Listbox(注意:Mikalos 可观察集合名为“Profile”)

ItemsSource="{Binding Profiles}"

这似乎是最明确的。相反,我只能让它工作的唯一方法是这样(ProfileList 是我用于可观察集合的名称):

ItemsSource="{Binding}" 

不确定它如何知道绑定到我的 observableCollection。我将在下面包含我的工作代码。

<Window x:Class="SavingButtons.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <DataTemplate x:Key="UserTemplate">
        <StackPanel Orientation="Horizontal">
            <Button Name="TestButton" Click="cmdDeleteUser_Clicked" Content="{Binding FirstName}" Width="100" Height="40"></Button> 
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<Grid>
    <Button Name="AddProfileButton" Content="Add Profile" HorizontalAlignment="Left" Margin="22,29,0,0" VerticalAlignment="Top" Width="75" Click="AddProfileButton_Click"/>
    <ListBox Name="ButtonHoldersListbox" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" ItemTemplate="{StaticResource UserTemplate}" HorizontalAlignment="Left" Height="202" Margin="22,69,0,0" VerticalAlignment="Top" Width="183" />
    <Button Name="DeleteUserButton" Click="DeleteUserButton_Click" Content="Delete User" HorizontalAlignment="Left" Margin="246,69,0,0" VerticalAlignment="Top" Width="105"/>
</Grid>

我的 ProfileCreator Cs:

public partial class NewProfile : Window
{
    public MainWindow mMain;
    public NewProfile(MainWindow main)
    {
        InitializeComponent();
        mMain = main;
    }

    //creates a new user out of all the info, inserts new user into the collection, adds new button
    private void ProfileFinishedLaunch_Click(object sender, RoutedEventArgs e)
    {
        ////Mikalos CODE-----------------------------------------------------------//
        var newUser = new User { FirstName = FirstNameTextBox.Text, LastName = LastNameTextBox.Text, imgPhoto = imgPhoto.Source };
        mMain.ProfileList.Add(newUser);

        mMain.ButtonHoldersListbox.DataContext = mMain.ProfileList;//Mikalo suggested not putting ListBox.DataContext here,
        //however, this is the only place it works. 

        mMain.Show();
        this.Hide();
        //---------------------------------------------------------------//   
    }
于 2013-09-02T19:52:47.183 回答
0

如果你将 itemsource 设置为 usercontrol 你不能直接操作它的项目。改为编辑它的 itemsource。给你一个简单的例子。

 public partial class MainWindow : Window
{
    ObservableCollection<int> ProfileList;
    public MainWindow()
    {
        InitializeComponent();
        ProfileList = new ObservableCollection<int>();
        this.DataContext = ProfileList;
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        Random r = new Random();
        int num = r.Next(100);
        ProfileList.Add(num);
        //lstShow.Items.Add(num);   error!
    }

    private void btnDel_Click(object sender, RoutedEventArgs e)
    {
        if (lstShow.SelectedIndex > -1)
        {
            ProfileList.Remove((int)lstShow.SelectedItem);
            //lstShow.Items.Remove((int)lstShow.SelectedItem);   error!
        }
    }
}
于 2013-09-02T08:13:37.880 回答