F#如何以编程方式在WPF标签上设置内容

Chr*_*lol 3 wpf f#

F#代码

open System
open System.Windows
open System.Windows.Controls

let resourceLocator = new Uri("/ConsoleApplication3;component/MainWindow.xaml", UriKind.Relative)

let lbl2 = (Application.LoadComponent(resourceLocator) :?> Window).FindName("lbl") :?> Label

let tb = (Application.LoadComponent(resourceLocator) :?> Window).FindName("tb") :?> TextBlock

let tbo = (Application.LoadComponent(resourceLocator) :?> Window).FindName("tbo") :?> TextBox

let value = "ROCK!"
let clickButton = fun _ -> 
    lbl2.Content <- "ROCK!"

let loadWindow() = 
    let resourceLocator = new Uri("/ConsoleApplication3;component/MainWindow.xaml", UriKind.Relative)
    let window = Application.LoadComponent(resourceLocator) :?> Window
    (window.FindName("clickButton") :?> Button).Click.Add(clickButton)
    window

[<STAThread>]
(new Application()).Run(loadWindow()) |> ignore
Run Code Online (Sandbox Code Playgroud)

我的Xaml WPF代码:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="500">
    <Grid>
        <Button Name="clickButton" Content="Click  me!" Height="40" Width="150" />
        <Label Name="lbl" Content="Label" HorizontalAlignment="Left" Margin="198,40,0,0" VerticalAlignment="Top"/>
        <TextBlock Name="tb" HorizontalAlignment="Left" Margin="198,201,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
        <TextBox Name="tbo" HorizontalAlignment="Left" Height="23" Margin="340,198,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

我打算用按钮点击更改Label:lbl的内容,但由于某种原因它无法正常工作,但无法理解为什么

Ree*_*sey 8

在这种情况下,问题是您不止一次加载组件.当您调用时clickButton,它使用绑定到绑定到与主实例分开的已加载窗口实例的绑定值的结果.

在这种情况下,你应该可以通过使用Application.Current.MainWindow获取已经显示的窗口来解决这个问题:

open System
open System.Windows
open System.Windows.Controls

let resourceLocator = new Uri("/ConsoleApplication3;component/MainWindow.xaml", UriKind.Relative)

// This needs to be a function, so it's not evaluated before the window is created
let getLbl2 () = Application.Current.MainWindow.FindName("lbl") :?> Label

let value = "ROCK!"
let clickButton = fun _ -> 
    let lbl = getLbl2()
    lbl.Content <- "ROCK!"

let loadWindow() = 
    let resourceLocator = new Uri("/ConsoleApplication3;component/MainWindow.xaml", UriKind.Relative)
    let window = Application.LoadComponent(resourceLocator) :?> Window
    (window.FindName("clickButton") :?> Button).Click.Add(clickButton)
    window

[<STAThread>]
(new Application()).Run(loadWindow()) |> ignore
Run Code Online (Sandbox Code Playgroud)

话虽这么说,我真的建议使用FsXaml来处理你的WPF资源.类型提供程序将为您提供对数据的类型安全访问,并使生活变得更加简单.

这可以使用FsXaml重写为:

open System
open System.Windows
open System.Windows.Controls
open FsXaml

type MainWindow = XAML<"MainWindow.xaml">

let loadWindow() = 
    let window = MainWindow().CreateRoot()
    let accessor = MainWindow.Accessor window
    accessor.clickButton.Click.Add(fun _ -> accessor.lbl.Content <- "ROCK!")
    window

[<STAThread>]
(new Application()).Run(loadWindow()) |> ignore
Run Code Online (Sandbox Code Playgroud)

请注意,在使用时FsXaml,您将获得成员的完整智能感知,并且您不再需要魔术字符串.

  • @ user3874490添加了.Current,这就是当你直接在答案中输入时会发生什么:) (2认同)