2015-02-24 74 views
1

在F#中,我無法執行我的請求對象中描述的操作。F#WPF:用戶控件:使用RegisterRoutedEvent的DependencyProperty

的缺失點聲明如下的C#事件的F#實現:

public event RoutedEventHandler DataChanged 
{ 
add { base.AddHandler(ucData.DataChangedEvent, value); } 
remove { base.RemoveHandler(ucData.DataChangedEvent, value); } 
} 

我怎麼能在F#做呢?

注意:在輸出wpf測試窗口中,用戶控件「ucData」起作用(內部綁定已在屬性和TextBox之間實現),但位於測試wpf窗口內的「DataChanged」事件偵聽器不會觸發/當我更改「數據」屬性的「通過代碼」或「通過窗口」(在wpf窗口內顯示的用戶控件上的鍵盤輸入)值時觸發。

謝謝(如allways)。

財產的用戶控制 「ucData」:

static let OnDataPropertyChanged (sender:DependencyObject) (e:DependencyPropertyChangedEventArgs) = 
    let control = unbox<ucData>(sender) 
    let newValue = unbox<double>(e.NewValue) 
    let oldValue = unbox<double>(e.OldValue) 
    System.Console.WriteLine 
     (sprintf 
      ">>> OnPropertyChanged 'ucData':'Data': Control Name: %s; Value: %f --> %f <<<" 
      control.Name oldValue newValue) 
    let argsEvent = new RoutedPropertyChangedEventArgs<double>(oldValue, newValue) 
    argsEvent.RoutedEvent <- ucData.DataChangedEvent // I get an ERROR here!!!! 
    control.RaiseEvent(argsEvent) 


static let OnCoerceDataProperty (sender:DependencyObject) (data:obj) = 
    let control = unbox<ucData>(sender) 
    let value = unbox<double>(data) 
    System.Console.WriteLine 
     (sprintf 
      ">>> OnCoerceValue 'ucData':'Data': Control Name: %s; Value: : %f <<<" 
      control.Name value) 
    box(value) 

static let OnValidateDataProperty (data:obj) = 
    System.Console.WriteLine 
     (sprintf 
      ">>> OnValidateValue 'ucData':'Data': Data %s <<<" 
      (data.ToString())) 
    data.GetType() = typeof<double> 

static let dpData = 
    DependencyProperty.Register("Data",typeof<double>, typeof<ucData>, 
     new FrameworkPropertyMetadata(0.0, 
      FrameworkPropertyMetadataOptions.Inherits, 
      new PropertyChangedCallback(OnDataPropertyChanged), 
      new CoerceValueCallback(OnCoerceDataProperty)), 
     new ValidateValueCallback(OnValidateDataProperty)) 

static member DataProperty = dpData 

[<Description("Specify the Numerical Data"); Category("UserData")>] 
member x.Data 
    with get() = 
     let res = x.GetValue(ucData.DataProperty) 
     (res :?> double) 
    and set (v:double) = 
     x.SetValue(ucData.DataProperty, v) 

用戶控制的事件 「ucData」:

static let reDataChangedEvent = 
    EventManager.RegisterRoutedEvent 
     ("DataChanged", RoutingStrategy.Bubble, 
      typeof<RoutedPropertyChangedEventHandler<double>>, typeof<ucData>) 

let dataChangedEvent = 
    let e = new Event<RoutedPropertyChangedEventHandler<double>,RoutedPropertyChangedEventArgs<double>>() 
    // Equialent to: 
    // public event RoutedPropertyChangedEventHandler<double> DataChanged 
    // { 
    //  add { AddHandler(DataChangedEvent, value); } 
    //  remove { RemoveHandler(DataChangedEvent, value); } 
    // } 
    // where DataChangedEvent is so defined: 
    // public static readonly RoutedEvent DataChangedEvent;   
    e 

[<CLIEvent>] 
static member DataChangedEvent with get() = reDataChangedEvent // I get an ERROR here!!! 

[<CLIEvent>] 
member x.DataChanged = dataChangedEvent.Publish 
+0

我還在努力... – 2015-03-04 18:48:10

回答

0

在這裏有 「ucData」(F#還有的全功能C#版本問題與C#和F#之間的「事件」不同定義):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.ComponentModel; 

namespace UCLibrary 
{ 
    /// <summary> 
    /// Interaction logic for UserControl1.xaml 
    /// </summary> 
    public partial class ucInput : UserControl 
    { 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     public static DependencyProperty DescriptionProperty; 

     public static DependencyProperty DataProperty; 

     public static DependencyProperty UnitOfMeasureProperty; 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     public static readonly RoutedEvent DescriptionChangedEvent; 

     public static readonly RoutedEvent DataChangedEvent; 

     public static readonly RoutedEvent UnitOfMeasureChangedEvent; 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     private static void OnDescriptionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      ucInput control = (ucInput)sender; 
      string oldValue = (string)e.OldValue; 
      string newValue = (string)e.NewValue; 

      string result = string.Format(
       ">>> OnPropertyChanged 'ucInput':'Description': Control Name: {0}; Value: {1} --> {2} <<<", 
       control.Name, 
       oldValue, 
       newValue); 

      System.Console.WriteLine(result); 

      RoutedPropertyChangedEventArgs<string> argsEvent = 
       new RoutedPropertyChangedEventArgs<string>(oldValue, newValue); 

      argsEvent.RoutedEvent = ucInput.DescriptionChangedEvent; 

      control.RaiseEvent(argsEvent); 

     } 

     private static void OnDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      ucInput control = (ucInput)sender; 
      double oldValue = (double)e.OldValue; 
      double newValue = (double)e.NewValue; 

      string result = string.Format(
       ">>> OnPropertyChanged 'ucInput':'Data': Control Name: {0}; Value: {1} --> {2} <<<", 
       control.Name, 
       oldValue, 
       newValue); 

      System.Console.WriteLine(result); 

      RoutedPropertyChangedEventArgs<double> argsEvent = 
       new RoutedPropertyChangedEventArgs<double>(oldValue, newValue); 
      argsEvent.RoutedEvent = ucInput.DataChangedEvent; 

      control.RaiseEvent(argsEvent); 

     } 

     private static void OnUnitOfMeasureChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      ucInput control = (ucInput)sender; 
      string oldValue = (string)e.OldValue; 
      string newValue = (string)e.NewValue; 

      string result = string.Format(
       ">>> OnPropertyChanged 'ucInput':'UnitOfMeasure': Control Name: {0}; Value: {1} --> {2} <<<", 
       control.Name, 
       oldValue, 
       newValue); 

      System.Console.WriteLine(result); 

      RoutedPropertyChangedEventArgs<string> argsEvent = 
       new RoutedPropertyChangedEventArgs<string>(oldValue, newValue); 
      argsEvent.RoutedEvent = ucInput.UnitOfMeasureChangedEvent; 

      control.RaiseEvent(argsEvent); 

     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     private static object OnCoerceDescriptionProperty(DependencyObject sender, Object data) 
     { 
      ucInput control = (ucInput)sender; 
      string value = (string)data; 

      value = value + ":"; 

      string result = string.Format(
       ">>> OnCoerceValue 'ucInput':'UnitOfMeasure': Control Name: {0}; Value: {1} <<<", 
       control.Name, 
       value); 

      System.Console.WriteLine(result); 

      return (object)value; 

     } 

     private static object OnCoerceDataProperty(DependencyObject sender, Object data) 
     { 
      ucInput control = (ucInput)sender; 
      double value = (double)data; 

      string result = string.Format(
       ">>> OnCoerceValue 'ucInput':'UnitOfMeasure': Control Name: {0}; Value: {1} <<<", 
       control.Name, 
       value); 

      System.Console.WriteLine(result); 

      return (object)value; 

     } 

     private static object OnCoerceUnitOfMeasureProperty(DependencyObject sender, Object data) 
     { 
      ucInput control = (ucInput)sender; 
      string value = (string)data; 

      value = "[" + value + "]"; 

      string result = string.Format(
       ">>> OnCoerceValue 'ucInput':'UnitOfMeasure': Control Name: {0}; Value: {1} <<<", 
       control.Name, 
       value); 

      System.Console.WriteLine(result); 

      return (object)value; 

     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     private static bool OnValidateDescriptionProperty(Object data) 
     { 

      string result = string.Format(
       ">>> OnValidateValue 'ucInput':'UnitOfMeasure': TypeOf: {0} <<<", 
       data.GetType().ToString()); 

      System.Console.WriteLine(result); 

      return (data.GetType() == typeof(String)); 

     } 

     private static bool OnValidateDataProperty(Object data) 
     { 

      string result = string.Format(
       ">>> OnValidateValue 'ucInput':'UnitOfMeasure': TypeOf: {0} <<<", 
       data.GetType().ToString()); 

      System.Console.WriteLine(result); 

      return (data.GetType() == typeof(Double)); 

     } 

     private static bool OnValidateUnitOfMeasureProperty(Object data) 
     { 

      string result = string.Format(
       ">>> OnValidateValue 'ucInput':'UnitOfMeasure': TypeOf: {0} <<<", 
       data.GetType().ToString()); 

      System.Console.WriteLine(result); 

      return (data.GetType() == typeof(String)); 

     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     static ucInput() 
     { 

      // ------------------------------------------------------------------------------------------ // 

      DescriptionProperty = 
       DependencyProperty.Register(
        "Description", typeof(string), typeof(ucInput), 
        new FrameworkPropertyMetadata("Description", 
          FrameworkPropertyMetadataOptions.Inherits, 
          new PropertyChangedCallback(OnDescriptionChanged), 
          new CoerceValueCallback(OnCoerceDescriptionProperty)), 
        new ValidateValueCallback(OnValidateDescriptionProperty) 
        ); 

      DataProperty = 
       DependencyProperty.Register(
        "Data", typeof(double), typeof(ucInput), 
        new FrameworkPropertyMetadata(0.0, 
          FrameworkPropertyMetadataOptions.Inherits, 
          new PropertyChangedCallback(OnDataChanged), 
          new CoerceValueCallback(OnCoerceDataProperty)), 
        new ValidateValueCallback(OnValidateDataProperty) 
        ); 

      UnitOfMeasureProperty = 
       DependencyProperty.Register(
       "UnitOfMeasure", typeof(string), typeof(ucInput), 
       new FrameworkPropertyMetadata("UM", 
          FrameworkPropertyMetadataOptions.Inherits, 
          new PropertyChangedCallback(OnUnitOfMeasureChanged), 
          new CoerceValueCallback(OnCoerceUnitOfMeasureProperty)), 
        new ValidateValueCallback(OnValidateUnitOfMeasureProperty) 
       ); 

      // ------------------------------------------------------------------------------------------ // 

      DescriptionChangedEvent = 
       EventManager.RegisterRoutedEvent(
        "DescriptionChanged", RoutingStrategy.Bubble, 
        typeof(RoutedPropertyChangedEventHandler<string>), typeof(ucInput)); 

      DataChangedEvent = 
       EventManager.RegisterRoutedEvent(
        "DataChanged", RoutingStrategy.Bubble, 
        typeof(RoutedPropertyChangedEventHandler<double>), typeof(ucInput)); 

      UnitOfMeasureChangedEvent = 
       EventManager.RegisterRoutedEvent(
        "UnitOfMeasureChanged", RoutingStrategy.Bubble, 
        typeof(RoutedPropertyChangedEventHandler<string>), typeof(ucInput)); 

     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     public ucInput() 
     { 
      InitializeComponent(); 
     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     [Description("Description of the Numerical Data"), Category("UserData")] 
     public string Description 
     { 
      get { return (string)GetValue(DescriptionProperty); } 
      set { SetValue(DescriptionProperty, value); } 
     } 

     [Description("Specify the Numerical Data"), Category("UserData")] 
     public double Data 
     { 
      get { return (double)GetValue(DataProperty); } 
      set { SetValue(DataProperty, value); } 
     } 

     [Description("Specify the 'Unit of Measure'"), Category("UserData")] 
     public string UnitOfMeasure 
     { 
      get { return (string)GetValue(UnitOfMeasureProperty); } 
      set { SetValue(UnitOfMeasureProperty, value); } 
     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

     [Description("Property 'Description' Changed"), Category("UserData")] 
     public event RoutedPropertyChangedEventHandler<string> DescriptionChanged 
     { 
      add { AddHandler (DescriptionChangedEvent, value); } 
      remove { RemoveHandler(DescriptionChangedEvent, value); } 
     } 

     [Description("Property 'Data' Changed"), Category("UserData")] 
     public event RoutedPropertyChangedEventHandler<double> DataChanged 
     { 
      add { AddHandler(DataChangedEvent, value); } 
      remove { RemoveHandler(DataChangedEvent, value); } 
     } 

     [Description("Property 'UnitOfMeasure' Changed"), Category("UserData")] 
     public event RoutedPropertyChangedEventHandler<double> UnitOfMeasureChanged 
     { 
      add { AddHandler(UnitOfMeasureChangedEvent, value); } 
      remove { RemoveHandler(UnitOfMeasureChangedEvent, value); } 
     } 

     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 

    } 
} 

這裏下面是XAML

<UserControl x:Class="UCLibrary.ucInput" 
     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:UCLibrary" 
     mc:Ignorable="d" 
     d:DesignHeight="30" d:DesignWidth="507"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="100*" MinWidth="100"/> 
     <ColumnDefinition Width="Auto" MinWidth="80"/> 
     <ColumnDefinition Width="70*" MinWidth="70"/> 
    </Grid.ColumnDefinitions> 
    <Label Name="lblDescription" 
      Margin="3" 
      Grid.Column="0" 
      Content="{Binding Description, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ucInput}}}"/> 
    <TextBox Name="txtData" 
      Margin="3" 
      Grid.Column="1" 
      Text="{Binding Data, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ucInput}}, StringFormat=N}"> 
    </TextBox> 
    <Label Name="lblUnitOfMeasure" 
      Margin="3" 
      Grid.Column="2" 
      Content="{Binding UnitOfMeasure, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ucInput}}}"/> 
</Grid>