0

So I have a command on a radio button that binds to a method that's outside of the itemsource (which is a ObservableCollection). This is producing an error when the radio button is clicked.

Error:

System.Windows.Data Error: 40 : BindingExpression path error: 'TaskSelectedCommand' property not found on 'object' ''Task' (HashCode=46555789)'. BindingExpression:Path=TaskSelectedCommand; DataItem='Task' (HashCode=46555789); target element is 'RadioButton' (Name=''); target property is 'Command' (type 'ICommand')

Data template XAML Code:

<Window.Resources>
        <DataTemplate x:Key="Tasks">
                <StackPanel>
                    <Grid>
                    <RadioButton ToolTip="Start tracker" GroupName="rdoExchange" Grid.Row="1" Grid.Column="1" Margin="2,0,10,1" Command="{Binding TaskSelectedCommand}" IsChecked="{Binding Selected}" Height="22" VerticalAlignment="Bottom"/>
                    <TextBox ToolTip="Task currently being tracked" IsEnabled="true" Margin="25,15,-375,4" Grid.Row="0" Grid.Column="0"  Text="{Binding Name}" RenderTransformOrigin="6.033,0.727" />
                    <TextBox Grid.Row="0" Margin="430,15,-455,4" Grid.Column="0"  Text="{Binding Time}"/>
                    </Grid>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>

Using the data template on a list box:

    <StackPanel Name="allTaskList" Orientation="Vertical" Margin="0,10,0,0">
        <ListBox IsSynchronizedWithCurrentItem="True"  Height="171" HorizontalAlignment="Left" ItemsSource="{Binding TaskList}" 
            HorizontalContentAlignment="Stretch" Margin="25,10,-523,0" VerticalAlignment="Top" Width="512" ItemTemplate="{StaticResource Tasks}"/>
    </StackPanel>

Task.cs code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace Sundial
{
    public class Task
    {
        public int id { get; set; }

        public string Name { get; set; }

        public double Time { get; set; }

        public bool Selected { get; set; }


    }
}

MainWindowViewModel.cs Code:

public ICommand TaskSelectedCommand
        {
            get
            {
                return mTaskSelected;
            }
            set
            {
                mTaskSelected = value;
            }

        }
public MainWindowViewModel()
        {

            TaskSelectedCommand = new RelayCommand(new Action<object>(TaskSelected));
            TaskList = new ObservableCollection<Task>();
    }



public void TaskSelected(object obj)
        {

            var task = TaskList.FirstOrDefault(i => i.Selected == true);

            if (task != null)
            {
                timer.Start();
            }


        }
public void AddTask(object obj)
        {
            TaskList.Add(new Task() { id = taskNum, Name = "Task", Selected = false, Time = 0.0 });
    }

This is not all the code, this is just the code that is in relation to the problem.

Noah R
  • 5,287
  • 21
  • 56
  • 75

2 Answers2

0

In scenarios like this you use a RelativeSource in the declaration of the binding for your command. Have a look at this answer: How do I use WPF bindings with RelativeSource?

Community
  • 1
  • 1
Boluc Papuccuoglu
  • 2,318
  • 1
  • 14
  • 24
0

As your XAML is written, WPF is looking for an object in the visual tree, starting at the ListBox, that has a non-null DataContext property. When it finds that object, it binds the ListBox's ItemsSource property to a property of that object called TaskList. I assume this binding is working, because you have not mentioned that there were any error messages about that binding failing.

Since TaskList is bound to the ListBox's ItemsSource property, I'm assuming it's a collection.

WPF next loops over all of the objects in the TaskList collection and creates a copy of the DataTemplate for each one, sticks it in a ListBoxItem object, and adds that to the ListBox's Items collection. It is while it builds the copy of the DataTemplate that it tries to bind the radio button to the TaskSelectedCommand property of the current object in the TaskList collection. It's not finding a TaskSelectedCommand property on that this object, so it fails and generates the error message.

You can either create a TaskSelectedCommand property on the items in the collection, or you can create one on the object that's got the TaskList collection property. In the first case, you make no changes to your XAML. In the second case, you have to change the binding for the TaskSelectedCommand so it's specifies a RelativeSource.

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123