Search code examples
c#wpflistboxitemsource

how to delete a selected template in a listbox


i have a listbox which has a data template binded to task from xml file,i want to delete selected template on button click,but its throws me an exception "Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead."

here is the code for xaml

 <TabItem>
        <Canvas Height="700" Width="850">
            <Canvas.Resources>
                <XmlDataProvider x:Key="Tasks" XPath="tasks"
       Source="http://store.tymesheet.com/templates/Graphic-Designer.xml"/>
                <DataTemplate x:Key="tasktemplate1">
                    <Canvas Height="50" Width="850" >
                        <Label Content="{Binding XPath=name}" Height="30"
                   Width="170" Canvas.Top="10" Canvas.Left="150" 
                   Background="LightGray"/>
                        <TextBox Height="30" Width="120" Canvas.Top="10"
                     Canvas.Left="370" Background="AliceBlue"/>
                        <Label  Canvas.Left="500" Canvas.Top="10">$</Label>
                        <Button Tag="{Binding}" Click="deletebuttonclick" 
                    Canvas.Top="12" Height="10" Width="30"
                    Canvas.Left="600"/>
                    </Canvas>
                </DataTemplate>
            </Canvas.Resources>
            <ListBox ItemTemplate="{StaticResource tasktemplate1}"
      ItemsSource="{Binding Path=ChildNodes, Source={StaticResource Tasks}}" 
      x:Name="tasklistbox" Height="700" Width="850"/>
            <Label Canvas.Top="-18" Canvas.Left="185">Select Task</Label>
            <Label Canvas.Top="-18" Canvas.Left="377" RenderTransformOrigin="0.58,0.462">Enter Bill Rates</Label>
            <Button Canvas.Left="39" Canvas.Top="575" Width="139">Click to add the task</Button>
        </Canvas>
    </TabItem>

here is the code behind for delete button

 private void deletebuttonclick(object sender,RoutedEventArgs e)
    {
        tasklistbox.Items.Remove(tasklistbox.SelectedItem);    
    }

where am i wrong?,help.thanx.


Solution

  • If you want to remove the item, then I would suggest to create ObservableCollection of XmlNode and bind ItemsSource with that. I suggested to use ObservableCollection because it implements INotifyCollectionChanged so whenever list is updated target which in your case is ListBox will automatically be updated.


    In code behind (Add System.Collections.ObjectModel namespace to use ObservableCollection<T>)

    public MainWindow()
    {
        InitializeComponent();
    
        XmlDocument doc = new XmlDocument();
        doc.Load("http://store.tymesheet.com/templates/Software-Developer.xml");
        var taskList = doc.ChildNodes.OfType<XmlNode>()
                        .Where(node => node.Name == "tasks")
                        .SelectMany(node => node.ChildNodes.OfType<XmlNode>());
        Tasks = new ObservableCollection<XmlNode>(taskList);
    
        this.DataContext = this;
    }
    
    public ObservableCollection<XmlNode> Tasks { get; set; }
    
    private void deletebuttonclick(object sender, RoutedEventArgs e)
    {
       XmlNode selectedNode = ((Button)sender).DataContext as XmlNode;
       Tasks.Remove(selectedNode);
    }
    

    Of course you need to update XAML as well:

    <ListBox ItemsSource="{Binding Tasks}"
             ItemTemplate="{StaticResource tasktemplate1}"
             x:Name="listBox" Height="700" Width="850"/>