【发布时间】:2016-03-19 16:54:17
【问题描述】:
为什么我的 ValueConverter 没有被触发?
当我的视图模型的构造函数被执行时,我的值转换器被触发。但是,当我为 Cells 属性分配新值时,它不会被触发。
我希望这条线会触发我的值转换器更新:
this.Cells <- grid |> cycleThroughCells
|> Map.toSeq
|> Seq.map snd
|> Seq.toList
但事实并非如此。
我有以下 ViewModel:
type ViewModel() as this =
inherit ViewModelBase()
let rowCount = 6
let mutable grid = rowCount |> createGrid
|> setCell { X=3; Y=1; State=Alive }
|> setCell { X=3; Y=0; State=Alive }
|> setCell { X=4; Y=1; State=Alive }
let mutable _cells = grid |> Map.toSeq
|> Seq.map snd
|> Seq.toList
let cycleHandler _ =
this.Cells <- grid |> cycleThroughCells
|> Map.toSeq
|> Seq.map snd
|> Seq.toList
member this.Play =
DelegateCommand ((fun _ -> let timer = createTimer 500 cycleHandler
do while true do
do Async.RunSynchronously timer), fun _ -> true) :> ICommand
member this.Cells
with get() = _cells
and set(value) =
_cells <- value
base.NotifyPropertyChanged(<@ this.Cells @>)
我的 ViewModelBase 如下:
open System.ComponentModel
open Microsoft.FSharp.Quotations.Patterns
type ViewModelBase () =
let propertyChanged =
Event<PropertyChangedEventHandler,PropertyChangedEventArgs>()
let getPropertyName = function
| PropertyGet(_,pi,_) -> pi.Name
| _ -> invalidOp "Expecting property getter expression"
interface INotifyPropertyChanged with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
member private this.NotifyPropertyChanged propertyName =
propertyChanged.Trigger(this,PropertyChangedEventArgs(propertyName))
member this.NotifyPropertyChanged quotation =
quotation |> getPropertyName |> this.NotifyPropertyChanged
我的 XAML 如下:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Client;assembly=Client"
Background="Black"
Title="Game of Life" Height="450" Width="500">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Window.Resources>
<local:StateToBrushConverter x:Key="StateToBrushConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Fill="{Binding Cells[0], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="0" Grid.Column="1" Fill="{Binding Cells[1], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="0" Grid.Column="2" Fill="{Binding Cells[2], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="0" Grid.Column="3" Fill="{Binding Cells[3], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="0" Grid.Column="4" Fill="{Binding Cells[4], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="0" Grid.Column="5" Fill="{Binding Cells[5], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="0" Fill="{Binding Cells[6], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="1" Fill="{Binding Cells[7], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="2" Fill="{Binding Cells[8], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="3" Fill="{Binding Cells[9], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="4" Fill="{Binding Cells[10], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="1" Grid.Column="5" Fill="{Binding Cells[11], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="0" Fill="{Binding Cells[12], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="1" Fill="{Binding Cells[13], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="2" Fill="{Binding Cells[14], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="3" Fill="{Binding Cells[15], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="4" Fill="{Binding Cells[16], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="2" Grid.Column="5" Fill="{Binding Cells[17], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="0" Fill="{Binding Cells[18], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="1" Fill="{Binding Cells[19], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="2" Fill="{Binding Cells[20], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="3" Fill="{Binding Cells[21], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="4" Fill="{Binding Cells[22], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="3" Grid.Column="5" Fill="{Binding Cells[23], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="0" Fill="{Binding Cells[24], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="1" Fill="{Binding Cells[25], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="2" Fill="{Binding Cells[26], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="3" Fill="{Binding Cells[27], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="4" Fill="{Binding Cells[28], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="4" Grid.Column="5" Fill="{Binding Cells[29], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="0" Fill="{Binding Cells[30], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="1" Fill="{Binding Cells[31], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="2" Fill="{Binding Cells[32], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="3" Fill="{Binding Cells[33], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="4" Fill="{Binding Cells[34], Converter={StaticResource StateToBrushConverter}}" />
<Rectangle Grid.Row="5" Grid.Column="5" Fill="{Binding Cells[35], Converter={StaticResource StateToBrushConverter}}" />
<Button Grid.Row="6" Grid.Column="1" Content="Go!" Command="{Binding Play}" />
</Grid>
</Window>
我的 ValueConverter 如下:
type StateToBrushConverter() =
interface IValueConverter with
member x.Convert(value, targetType, parameter, culture) =
let cell = value :?> Cell
match cell.State with
| Alive -> SolidColorBrush(Colors.LightGreen) :> obj
| Dead -> SolidColorBrush(Colors.Black) :> obj
member x.ConvertBack(value, targetType, parameter, culture) = failwith "Not implemented yet"
【问题讨论】:
-
这是非常非常糟糕的代码。你想做什么?
-
但我强烈建议您使用FSharp.ViewModule.Core - 这样您就可以将苍蝇与肉饼分开 =)
-
@ScottNimrod 这是一本不同的书,你看了吗?它更接近 F#,并解释了如何从 lambda 演算转到使用 let 语句的 ML。如果有一本关于 OCAML 的书,例如 Think OCaml - How to Think Like a (Functional) Programmer,您应该能够看到 F# 语言是如何演变的,并更好地理解函数式程序如何更像数学而不是食谱。
-
@ScottNimrod 如果在@ 和 OP 名称之间放置一个空格,则不会通知 OP。由于空间原因,我没有收到任何通知。我只是通过检查这个问题才看到评论。
-
@ScottNimrod 绑定到集合中通常很奇怪 - 我会确保在主 (UI) 线程上调用你的 setter,看看这是否会有所不同。