Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF绑定到具有listview列参数的方法的结果_C#_Wpf_Listview_Binding_Objectdataprovider - Fatal编程技术网

C# WPF绑定到具有listview列参数的方法的结果

C# WPF绑定到具有listview列参数的方法的结果,c#,wpf,listview,binding,objectdataprovider,C#,Wpf,Listview,Binding,Objectdataprovider,我正在使用C#,WPF,.NET标准,Visual Studio。所有最新或几乎最新的版本 这是我的datacontext模型(在名为ProgrammingManagerRapi的单独库中创建): 公共类main模型 { 公共列表项目{get;set;} ... } 其中包含定义如下的Project类型的对象列表(在单独的库编程ManageRapi中,在目录模型中),一些属性和一些方法: public class Project { public int Id { get; set;

我正在使用C#,WPF,.NET标准,Visual Studio。所有最新或几乎最新的版本

这是我的datacontext模型(在名为ProgrammingManagerRapi的单独库中创建):

公共类main模型
{
公共列表项目{get;set;}
...
}
其中包含定义如下的Project类型的对象列表(在单独的库编程ManageRapi中,在目录模型中),一些属性和一些方法:

public class Project
{
    public int Id { get; set; }
    ...
    public TimeSpan? TotalWorkedTime(bool subtasksIncluded = true)
    {
        if (Id < 0)
            return null;
        else 
            return new TimeSpan(...);
    }
    ...
}
公共类项目
{
公共int Id{get;set;}
...
公共时间跨度?总工作时间(bool subtasksinclude=true)
{
if(Id<0)
返回null;
其他的
返回新的时间跨度(…);
}
...
}
在主窗口中,我有一个ListView,我想用它列出项目及其属性。
我有很多属性和一些方法,它们根据布尔参数返回值

我了解到,在这种情况下,我应该使用ObjectDataProvider,因此我尝试如下:

xmlns:s="clr-namespace:System;assembly=mscorlib" 
xmlns:API.Models="clr-namespace:ProgrammingManagerAPI.Models;assembly=ProgrammingManagerAPI"

<Window.Resources>
    <ObjectDataProvider x:Key="yourStaticData"
            ObjectType="{x:Type API.Models:Project}"
            MethodName="TotalWorkedTime" >
        <ObjectDataProvider.MethodParameters>
            <s:Boolean>false</s:Boolean>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

 <Grid Grid.Row="1" Grid.Column="0" Margin="10">
     <ListView Margin="10" ItemsSource="{Binding Projects}" HorizontalAlignment="Center" HorizontalContentAlignment="Center">
         <ListView.View>
             <GridView>
                <GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Id" DisplayMemberBinding="{Binding Id}" />
                <GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="TotalWorkedTime" DisplayMemberBinding="{Binding Path=., Source={StaticResource yourStaticData}}" />
             </GridView>
         </ListView.View>
     </ListView>
 </Grid>
xmlns:s=“clr命名空间:系统;程序集=mscorlib”
xmlns:API.Models=“clr命名空间:ProgrammingManagerAPI.Models;assembly=ProgrammingManagerAPI”
假的
对函数TotalWorkedTime的调用被触发,因为断点被命中。但只命中一次,而我已经创建了4个对象进行测试。 此外,它像静态函数一样命中,不像其他属性那样针对对象的每个实例。在即时窗口中,我试图查看哪些是其他属性,哪些是空属性。当Id列被点击时,所有属性都可用于项目的每个实例。 此外,我观察到它在调用Id属性getter之前被命中

我尝试过很多版本,比如无路径、绑定和其他许多方式


任何人都可以指出我的错误吗?
对象数据提供程序
在您有一个对象实例(或静态类)要绑定到,但您使用的是
项控件(
列表视图
)时非常有用,这会使事情更加复杂

你需要的是一份工作。它通过调用函数并返回结果来获取对象并“转换”它。老实说,我希望能通过谷歌搜索找到一个,但我没能找到。我想我可能迟早会使用类似的东西,所以我继续建造了一个。这支持任何类型的对象,其任何函数名包含任意数量的参数

    public class FunctionConverter : IValueConverter
    {
        public string FunctionName { get; set; }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value.GetType().GetMethod(FunctionName).Invoke(value, (object[])parameter);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    }
下面是一个您可以如何使用它的示例:

MainWindow.xaml.cs:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            TestInstance = new Test();
            InitializeComponent();
        }

        public Test TestInstance { get; set; }

    }

    public class Test
    {
        public string Foo(string bar)
        {
            return bar;
        }
    }
MainWindow.xaml:

    <Grid>
        <Grid.Resources>
            <KHS:FunctionConverter x:Key="FuncCon" FunctionName="Foo"/>
        </Grid.Resources>

        <TextBlock>
            <TextBlock.Text>
                <Binding Path="TestInstance" Converter="{StaticResource FuncCon}">
                    <Binding.ConverterParameter>
                        <x:Array Type="sys:Object">
                            <sys:String>Hello World</sys:String>
                        </x:Array>
                    </Binding.ConverterParameter>
                </Binding>
            </TextBlock.Text>
        </TextBlock>
    </Grid>

你好,世界
将转换器声明为资源,就像对
ObjectDataProvider
所做的那样,并将
FunctionName
设置为要调用的函数的名称。然后转换器使用运行该函数并返回结果

您可以通过绑定的
ConverterParameter
属性传递函数的参数,这将允许您为列表中的不同项传递不同的值。在本例中,我将字符串
“Hello World”
传递给函数
Foo
,该函数只返回传递的内容


最后几点注意:这个转换器只有一种工作方式。所提供的转换器不检查
null
,并且在未找到
FunctionName
时没有适当的处理。使用这样的绑定不允许像依赖项属性那样提供更新通知。

为什么不简单地使用TotalWorkedTime属性并像
DisplayMemberBinding=“{binding TotalWorkedTime}”
那样绑定到它,因为它是参数化的。我至少有几个(目前)方法根据某些需求返回值。如果我有3个参数,我需要用getter生成8个属性。但是如果我有5个或6个参数,它将是完全无法维护的。你将不需要同样数量的ObjectDataProviders?这就是你的意思。你说得对。然而,我不想弄乱我的API项目。你能提出一些解决办法吗?我的意思是只要告诉我一些对我的案子有用的东西?我不想以包含数百个属性的对象结束,这些属性的getter包括TotalWorkedTime1、TotalWorkedTime2、TotalWorkedTime3、…、TotalWorkedTime999。我相信WPF是如此灵活,所以它允许使用一些更智能的方式,而且肯定有人和我有类似的问题。编辑:顺便说一句,谢谢你的评论:)你是正确的。对不起,但对我来说,完全不清楚为什么应该显示在ItemsControl中的项应该有这么多属性。您希望在该列表视图中有多少列?属性不应该超过大致的列数。非常感谢。我已登录以感谢您。你是WPF的英雄。很有魅力。@ninidow359我很乐意。
    <Grid>
        <Grid.Resources>
            <KHS:FunctionConverter x:Key="FuncCon" FunctionName="Foo"/>
        </Grid.Resources>

        <TextBlock>
            <TextBlock.Text>
                <Binding Path="TestInstance" Converter="{StaticResource FuncCon}">
                    <Binding.ConverterParameter>
                        <x:Array Type="sys:Object">
                            <sys:String>Hello World</sys:String>
                        </x:Array>
                    </Binding.ConverterParameter>
                </Binding>
            </TextBlock.Text>
        </TextBlock>
    </Grid>