You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用WCF取数绑定ListView仅显示计数无正确值问题

问题成因
  • 最核心的问题是WCF数据契约序列化标记缺失:你定义的InterventiiCuEchipament类中,仅EchipamentInterventie属性添加了[DataMember]特性,其余需要传输的属性均未标记。WCF序列化时仅会识别带[DataMember]标记的属性,未标记属性的值不会被写入传输消息,客户端反序列化后这些属性均为类型默认值,无法绑定展示正确内容。
  • 服务端查询存在延迟执行风险:你直接返回EF生成的IQueryable查询对象,该类型的查询为延迟执行,WCF序列化枚举结果时如果数据上下文dataP已经释放,会触发查询异常,也可能导致返回结果结构不完整。
  • 客户端调用和控件配置存在缺陷:直接用.Result获取异步方法返回值容易造成UI线程死锁;如果ListView未配置对应列的字段绑定规则,就算数据正确传输到客户端,也无法识别要展示的字段,只会输出集合/对象的默认字符串表示。
  • 服务契约存在冗余标记:GetInterventiiCuEchipaments方法上方重复写了两次[OperationContract],虽然不一定直接引发错误,但属于不规范配置。
解决方法
  1. 补全数据契约标记,清理冗余配置
    给所有需要跨WCF传输的属性添加[DataMember]特性,删除服务契约中重复的[OperationContract]标记,修正后代码如下:
public interface IServicePl
{
    [OperationContract]
    IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments();
}

[DataContract]
public class InterventiiCuEchipament
{
    [DataMember]
    public string EchipamentInterventie { get; set; }
    [DataMember]
    public int id_interventie { get; set; }
    [DataMember]
    public string tip_interventie { get; set; }
    [DataMember]
    public string responsabil { get; set; }
    [DataMember]
    public DateTime data_finalizare { get; set; }
    [DataMember]
    public bool status { get; set; }
}
  1. 修正服务端查询逻辑,消除延迟执行问题
    在服务端执行查询时用ToList()立即加载结果到内存集合,避免序列化时数据上下文已释放的问题,同时补全异常处理,修正后代码:
public IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments()
{
    try
    {
        // 建议用using包裹EF上下文,确保资源正确释放
        using (var dataP = new YourDbContext()) // 替换为你实际的EF上下文类名
        {
            var query = from sel1 in dataP.interventiis
                        join sel2 in dataP.sesizaris
                        on sel1.id_interventie equals sel2.id_sesizare
                        select new InterventiiCuEchipament()
                        {
                            id_interventie = sel1.id_interventie,
                            EchipamentInterventie = sel2.echipament,
                            tip_interventie = sel2.tip_sesizare,
                            responsabil = sel1.responsabil,
                            data_finalizare = (DateTime)sel1.data_finalizare,
                            status = (bool)sel1.status
                        };
            // 立即执行SQL查询,转为内存集合再返回
            return query.ToList();
        }
    }
    catch (Exception ex)
    {
        throw new FaultException($"数据查询失败:{ex.Message}");
    }
}
  1. 配置ListView绑定规则,修正客户端调用逻辑
    如果使用WPF的ListView控件,先在XAML中配置GridView列和对应字段的绑定关系:
<ListView x:Name="InterventiiList">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="干预ID" DisplayMemberBinding="{Binding id_interventie}"/>
            <GridViewColumn Header="关联设备" DisplayMemberBinding="{Binding EchipamentInterventie}"/>
            <GridViewColumn Header="干预类型" DisplayMemberBinding="{Binding tip_interventie}"/>
            <GridViewColumn Header="负责人" DisplayMemberBinding="{Binding responsabil}"/>
            <GridViewColumn Header="完成时间" DisplayMemberBinding="{Binding data_finalizare}"/>
            <GridViewColumn Header="完成状态" DisplayMemberBinding="{Binding status}"/>
        </GridView>
    </ListView.View>
</ListView>

客户端调用WCF服务时改用await异步方式,避免.Result造成的UI线程死锁,不需要手动调用Items.Refresh(),赋值ItemsSource后控件会自动刷新:

if (client.InnerChannel.State != CommunicationState.Faulted)
{
    var ListaInterventii = (await client.GetInterventiiCuEchipamentsAsync()).ToList();
    InterventiiList.ItemsSource = ListaInterventii;
}

如果使用WinForm平台的ListView控件,需要先将控件的View属性设置为Details,添加对应列头后,通过循环遍历结果集创建ListViewItem添加到控件中即可。

  1. 更新客户端服务引用
    服务端代码修改完成后,在客户端项目中找到对应的WCF服务引用,右键选择“更新服务引用”,重新生成客户端代理类,确保客户端的数据契约定义和服务端一致。

内容的提问来源于stack exchange,提问作者BMA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 10:09:47