简体   繁体   English

如何在 C# Wpf UserControl 中使用 F# 对象/记录

[英]How to use F# objects/records in C# Wpf UserControl

(Newbie question). (新手问题)。 My main application is running in F#.我的主要应用程序在 F# 中运行。 From the F# application, I am calling a print routine on a separate background thread.从 F# 应用程序中,我在单独的后台线程上调用打印例程。 This print routine uses the below wpf xaml usercontrol in a separate C# project to format the page.此打印例程在单独的 C# 项目中使用以下 wpf xaml 用户控件来格式化页面。

My problem is that the Account object is defined in F# and used in C# -- except that it does not work.我的问题是帐户 object 在 F# 中定义并在 C# 中使用 - 除了它不起作用。

Error: The type 'Account' is not compatible with the type 'IAccount'错误:“Account”类型与“IAccount”类型不兼容

Is there anyway to have these two languages play nice together?反正有没有让这两种语言一起玩得很好?

(Is FsXaml a possibility?) (FsXaml 有可能吗?)

Thanks for any help or suggestions.感谢您的任何帮助或建议。

TIA TIA

F#

let workSheetHeader (a:Account) (encounterTime: Nullable<DateTime> ) = 
            let Insurance = "Self Pay"
            let firstEncounter,lastEncounter = getFirstAndLastEncounter(a,encounterTime)
            let account = {Account.birthDate = "11/30/1999"; lastName = "lastname"; firstName = "firstname"; chartNumber = 1776; doNotSee = false; mi ="i" }
            let ws =  new WorksheetHeader (account, firstEncounter, lastEncounter, Insurance)
            ws :> FrameworkElement


WPF XAML

<UserControl x:Class="StargateIX.PrintingAndReports.WorksheetHeader"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:StargateIX.PrintingAndReports"
             mc:Ignorable="d" 
             d:DesignHeight="70" d:DesignWidth="816">

    <UserControl.Resources>
        <!--Without the x:Key, this will style ALL the TextBlocks-->
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontSize" Value="12" />
        </Style>
        <Style x:Key="Title" TargetType="{x:Type TextBlock}">
            <Setter Property="FontSize" Value="14" />
            <Setter Property="TextAlignment" Value="Center" />
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Top" />
        </Style>
    </UserControl.Resources>
    <Grid>
        <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top"  Margin="24,0" >
            <TextBlock  Text="address 1"  />
            <TextBlock  Text="address 2"     />
            <TextBlock  Text="address 3"  />
        </StackPanel>
        <StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Margin="24,0">
            <TextBlock  Text="Chart Number" Name="textblockChartNumber" />
            <TextBlock  Text="Bd: 4/15/1960" Name="textblockBirthDate"  />
            <StackPanel   Orientation="Horizontal">
                <!--Last Encounter Date-->
                <TextBlock Text="First Visit: " />
                <TextBlock Text="{Binding FirstEncounter}" />
            </StackPanel>
            <StackPanel   Orientation="Horizontal">
                <!--Last Encounter Date-->
                <TextBlock Text="Last Visit: " />
                <TextBlock Text="{Binding LastEncounter}" />
            </StackPanel>

        </StackPanel>

        <TextBlock
            Style="{StaticResource Title}" Name="textblockPatientName"
            Text="Test Name" Width="332" Margin="242,0,242,0" />

        <!--Today's Date-->
        <TextBlock x:Name="textblockTodaysDate" HorizontalAlignment="Left" Margin="368,33,0,0" Text="11/04/2015" VerticalAlignment="Top"/>

        <!--Insurance-->
        <TextBlock HorizontalAlignment="Left" Height="16" Margin="24,48,0,0" Text="{Binding Insurance}" VerticalAlignment="Top" Width="209"/>

    </Grid>
</UserControl>


Code Behind:

using System;
using System.Windows.Controls;

namespace StargateIX.PrintingAndReports
{

    public interface IAccount
    {
        string lastName { get; }
        string firstName { get; }
        string  mi { get; }
        string birthDate { get; }
        int chartNumber { get;}
        bool doNotSee { get;}
    }

    /// <summary>
    /// Interaction logic for WorksheetHeader.xaml
    /// </summary>
    public partial class WorksheetHeader : UserControl
    {
        public WorksheetHeader(IAccount account, DateTime? firstEncounter, DateTime? lastEncounter, string insurance)
        {
            DataContext = this;
            FirstEncounter = firstEncounter;
            LastEncounter = lastEncounter;
            Insurance = insurance;

            InitializeComponent();

        //    var model = new ServiceService(service);

            textblockTodaysDate.Text = DateTime.Today.ToShortDateString();
        //    textblockBirthDate.Text = $"Bd: {account.birthDate:D}";
        //    textblockChartNumber.Text = $"C#: {account.chartNumber}";
        //    textblockPatientName.Text = PatientNameService.ProperName(account);
        }
        public DateTime? FirstEncounter { get; private set; }
        public string Insurance { get; private set; }
        public DateTime? LastEncounter { get; private set; }
    }
}

#Addendum: As suggested below, I moved the definition and interface in F# to its own project, then referenced this project from the C# XAML. #附录:如下所示,我将F#中的定义和接口移到了自己的项目中,然后从C# XAML中引用了这个项目。 It now at least compiles.它现在至少可以编译了。 Here is the new definitions (in its own project):这是新的定义(在它自己的项目中):

module Contracts =

    type IAccount =
       abstract member lastName : string with get
       abstract member firstName : string with get
       abstract member mi : string with get
       abstract member birthDate: string with get
       abstract member chartNumber: int with get
       abstract member doNotSee: bool with get  
     

    type Account = 
       {
            lastName: string
            firstName: string
            mi: string
            birthDate: string
            chartNumber: int
            doNotSee: bool
       } 
       interface IAccount with
                member this.birthDate with get() = this.birthDate
                member this.chartNumber with get() = this.chartNumber
                member this.doNotSee with get() = this.doNotSee
                member this.firstName with get() = this.firstName
                member this.lastName with get() = this.lastName
                member this.mi with get() = this.mi

Is there any other way, or perhaps a better way of doing this?有没有其他方法,或者可能有更好的方法来做到这一点?

TIA TIA

If you are only exposing the interface, are not concerned about the concrete type, you can also use an object expression.如果只暴露接口,不关心具体类型,也可以使用 object 表达式。

type IAccount =
    abstract member lastName : string with get
    abstract member firstName : string with get
  

 let createAccount fstName lstName =
    { new IAccount with
        member _.firstName = fstName
        member _.lastName = lstName
    }
        

A record implementing the interface is good as well.实现接口的记录也很好。 F# forces you to have acyclic dependencies, so plan ahead. F# 强迫你有非循环依赖,所以提前计划。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM