C# 如何使用绑定到模板外部方法的命令?

C# 如何使用绑定到模板外部方法的命令?,c#,xaml,C#,Xaml,所以我在单选按钮上有一个命令,它绑定到itemsource(这是一个ObservableCollection)之外的方法。这产生了一个错误 单击单选按钮时 错误: System.Windows.Data Error: 40 : BindingExpression path error: 'TaskSelectedCommand' property not found on 'object' ''Task' (HashCode=46555789)'. BindingExpression:Path=

所以我在单选按钮上有一个命令,它绑定到itemsource(这是一个ObservableCollection)之外的方法。这产生了一个错误 单击单选按钮时

错误:

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')
<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>
    <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>
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; }


    }
}
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 });
    }
数据模板XAML代码:

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')
<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>
    <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>
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; }


    }
}
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 });
    }
MainWindowViewModel.cs代码:

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')
<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>
    <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>
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; }


    }
}
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 });
    }
public ICommand task selected命令
{
得到
{
返回所选项目;
}
设置
{
mTaskSelected=值;
}
}
公共主窗口视图模型()
{
TaskSelectedCommand=newrelaycommand(新操作(TaskSelected));
TaskList=新的ObservableCollection();
}
已选择公共对象(对象对象对象)
{
var task=TaskList.FirstOrDefault(i=>i.Selected==true);
如果(任务!=null)
{
timer.Start();
}
}
公共无效添加任务(对象obj)
{
添加(新任务(){id=taskNum,Name=“Task”,Selected=false,Time=0.0});
}

这不是全部代码,这只是与问题相关的代码。

在类似的场景中,在命令的绑定声明中使用相对资源。看看这个答案:

在编写XAML时,WPF正在视觉树中查找一个对象,从
列表框开始,该对象具有非空的
DataContext
属性。当找到该对象时,它将
列表框
项资源
属性绑定到该对象名为
任务列表
的属性。我假设这个绑定正在工作,因为您没有提到有任何关于绑定失败的错误消息

由于
TaskList
绑定到
ListBox的ItemsSource
属性,因此我假设它是一个集合

WPF接下来在
TaskList
集合中的所有对象上循环,并为每个对象创建
DataTemplate
的副本,将其粘贴到
ListBoxItem
对象中,并将其添加到
ListBox的Items
集合中。当它构建
数据模板的副本时,它会尝试将单选按钮绑定到
任务列表
集合中当前对象的
TaskSelectedCommand
属性。它没有在该对象上找到
TaskSelectedCommand
属性,因此它失败并生成错误消息


您可以在集合中的项目上创建一个
TaskSelectedCommand
属性,也可以在具有
TaskList
集合属性的对象上创建一个属性。在第一种情况下,您不需要更改XAML。在第二种情况下,您必须更改
TaskSelectedCommand
的绑定,因此它指定了一个
RelativeSource

知道为什么会这样吗?