【发布时间】:2015-02-21 16:51:15
【问题描述】:
我尝试仅使用 F#(版本 12.0.30815.0 + Framework 4.5)创建“UserControl”“By-Code”,因为我更喜欢这种“方式”(C# 和 F# 之间没有混合)。
注意:我必须在输入表单中显示单个类的多个属性,因此此用户控件需要实现绑定功能以将“输出”连接到类的属性。
我尝试修改窗口内的数值(即 1200 或 400)或使用键盘上的 TAB 键在控件之间移动焦点,但似乎已锁定。
无法更新数值。我只能删除一个或多个单个数字,没有任何更新。
我在 UserControls 中实现的事件“dataChangedEvent”中可能存在概念错误(即“ucData”控件的“Data”属性 - 请参阅代码)。它类似于:“INotifyPropertyChanged”。
注意:也许这个事件实现中的错误也存在于 UserControl 的“描述”和“UnitOfMeasure”属性中。
有人可以帮我在下面报告的代码行中发现我的错误/错误在哪里吗?
非常感谢。
ANN
定义用户控制
type ucData() as this =
inherit Windows.Controls.UserControl()
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 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
let grid =
let c = new Grid()
let colData = new ColumnDefinition()
colData.MinWidth <- 70.
c.ColumnDefinitions.Add( colData )
c
let data=
let c = new TextBox()
c.Margin<- new Thickness(3.0)
c.SetValue(Grid.ColumnProperty,1)
c
do
grid.Children.Add(data) |> ignore
this.AddChild(grid) |> ignore
let bData = new Binding()
bData.Path <- new PropertyPath("Data")
bData.StringFormat <- "N"
bData.ConverterCulture <- System.Globalization.CultureInfo.InvariantCulture
bData.Mode <- BindingMode.TwoWay
bData.RelativeSource <- new RelativeSource(RelativeSourceMode.FindAncestor,typeof<ucData>,1)
data.SetBinding(TextBox.TextProperty, bData) |> ignore
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 )
[<CLIEvent>]
static member DataChangedEvent with get() = reDataChangedEvent // I get an ERROR here!!!
[<CLIEvent>]
member x.DataChanged = dataChangedEvent.Publish
创建窗口
type TestWindow() as this =
inherit Window()
let c1 = new ucData()
let c2 = new ucData()
do
c1.Name <- "Data1"
c2.Name <- "Data2"
this.Width <- 300.
this.Height <- 300.
let sp = new StackPanel()
c1.Data <- 1200.
c2.Data <- 400.
sp.Children.Add(c1) |> ignore
sp.Children.Add(c2) |> ignore
c1.DataChanged.Add( fun args ->
MessageBox.Show("The button labeled \"" + c1.Data.ToString()) |>ignore )
c2.DataChanged.Add( fun args ->
MessageBox.Show("The button labeled \"" + c1.Data.ToString()) |>ignore )
this.Content <- sp
运行测试窗口
let w = new TestWindow()
w.Show()
【问题讨论】:
-
建议:只显示触发错误所需的最少代码量
标签: wpf f# event-handling wpf-controls dependency-properties