将viewmodel从C#转换为F#

时间:2015-11-16 12:37:00

标签: f# c#-to-f#

以下ViewModel在F#中的外观如何?

namespace MVVMExample
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _firstName;    
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = value;
                RaisePropertyChanged("FirstName");
            }
        }

        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set
            {
                _lastName = value;
                RaisePropertyChanged("LastName");
            }
        }

        public string GetFullName()
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }

        protected void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

注:

我是F#的新手,确实想了解如何简化C#中的代码。

2 个答案:

答案 0 :(得分:3)

我更喜欢使用基类ViewModel继承并公开使用引号的接口,因此我不需要手工提供字符串属性名称(这对代码重构不友好)。

请注意,根据问题的接受答案:Is it possible to use CallerMemberNameAttribute in f# F#不支持[<CallerMemberName>]属性,因此我使用引号来执行此操作。

如果您在C#中定义基类ViewModel类并从F#中继承该类,您仍然可以获得[<CallerMemberName>]的好处。出于这个答案的目的,我将向您展示一个纯粹的F#解决方案。

type ViewModel () =
    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

然后从中获取您的具体ViewModel

type NimrodViewModel() =
    inherit ViewModel()
    let mutable firstName = ""
    let mutable lastName = ""

    member this.FirstName
        with get() = firstName 
        and set(value) =
            firstName <- value
            base.notifyPropertyChanged(<@ this.FirstName @>)

    member this.LastName
        with get() = lastName 
        and set(value) =
            lastName <- value
            base.notifyPropertyChanged(<@ this.LastName @>)

    member this.GetFullName() = 
        sprintf "%s %s" (this.FirstName) (this.LastName)

答案 1 :(得分:1)

使用FSharp.Desktop.UI,它看起来像这样:

if (c >= 0 && c <= 9)

ViewModel的实例将由[<AbstractClass>] type ViewModel() = inherit Model() abstract FirstName: string with get, set abstract LastName: string with get, set [<DerivedProperty>] member this.FullName = sprintf "%s %s" this.FirstName this.LastName 创建。

通过使let model: MyViewModel = ViewModel.Create()属性并使用FullName属性进行装饰,任何绑定到它的控件都会在其所依赖的任何属性发生更改时自动获得更改通知。

我知道您没有要求使用库的示例,但我希望展示在使用正确的社区库时F#的简洁程度。