#c# #wpf #f#
#c# #wpf #f#
Вопрос:
(Вопрос новичка). Мое основное приложение работает на F #. Из приложения F # я вызываю процедуру печати в отдельном фоновом потоке. Эта процедура печати использует приведенный ниже пользовательский элемент управления wpf xaml в отдельном проекте C # для форматирования страницы.
Моя проблема в том, что объект Account определен в F # и используется в C # — за исключением того, что он не работает.
Ошибка: тип ‘Account’ несовместим с типом ‘IAccount’
Есть ли в любом случае, чтобы эти два языка хорошо сочетались?
(Возможен ли FsXaml?)
Спасибо за любую помощь или предложения.
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; }
}
}
#Дополнение: как предложено ниже, я переместил определение и интерфейс в F # в его собственный проект, а затем сослался на этот проект из C # XAML. Теперь он, по крайней мере, компилируется. Вот новые определения (в собственном проекте):
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
Есть ли какой-либо другой способ или, возможно, лучший способ сделать это?
TIA
Комментарии:
1. Поддерживает ли ваш
Account
типIAccount
интерфейс?2. Федорсойкин Я попытался создать интерфейс IAccount в проекте F #. Возможно, я сделал это неправильно, но это не сработало. 🙁
3. Хорошо, можете ли вы показать, как вы пытались, и объяснить, что не сработало? Мы не можем предложить решение, пока не увидим проблему.
4. @FyodorSoikin Спасибо. Пожалуйста, смотрите приложение. Я думаю, что нужно переместить учетную запись и IAccount в свой собственный проект, чтобы избежать перекрестных ссылок на проекты, и тогда проекты C # и F # смогут ссылаться на новый проект. Это способ сделать это? (Сейчас он компилируется). Спасибо.
5. Нет, не FsXaml. Вместо этого вам нужен Elmish.WPF .
Ответ №1:
Если вы предоставляете только интерфейс, вас не интересует конкретный тип, вы также можете использовать объектное выражение.
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
}
Запись, реализующая интерфейс, также хороша. F # заставляет вас иметь ациклические зависимости, поэтому планируйте заранее.