【问题标题】:mvvmlight wpf how to raise frame source property wpf c#mvvmlight wpf 如何提高框架源属性 wpf c#
【发布时间】:2018-07-21 10:48:59
【问题描述】:

(参见下面的解决方案)

努力学习 MVVMLight 和 WPF。很高兴获得带有 3 个按钮的框架的页面导航,并让 CanExecute RelayCommand 功能适用于这些按钮。

但是,当我使用框架中的“后退”和“前进”按钮更改页面时,框架导航按钮似乎没有提升视图模型中框架源属性 FrameURI 的 propertychanged。在 RelayCommand 执行中,我正在查看 FrameURI 属性以确定可以执行的按钮命令。我在想,在按下 Frame FWD 或 BACK 按钮后,我需要在 viewmodel 中引发 FrameURI 属性的propertychange。看起来我可以在来自NavigationService Class 的 Navigated 或 LoadCompleted EVENT 中做到这一点。这是解决这个问题的最好方法吗?也许有更简单的方法?

此处的正确行为:

当按下框架返回按钮时,此处无法正常工作。页面发生了变化(很好),但是 Middle canexecute 按钮没有正确更新。请参阅下面的属性和中继命令。

MVVMINPCPROPERTY sn-p

    public const string FrameUriPropertyName = "FrameUri";

    private Uri _frameUri;

    /// <summary>
    /// Sets and gets the FrameUri property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public Uri FrameUri
    {
        get
        {
            return _frameUri;
        }
        set
        {
            Set(FrameUriPropertyName, ref _frameUri, value);
        }
    }

框架的 XAML

    <Frame  x:Name="MainFrameDS"  Source="{Binding FrameUri}"  HorizontalAlignment="Left" Height="211" Margin="109,88,0,0" VerticalAlignment="Top" Width="258"/>

RelayCommand 示例

    private RelayCommand _changeToLastPage;

    /// <summary>
    /// Gets the ChangeToLastPage.
    /// </summary>
    public RelayCommand ChangeToLastPage
    {
        get
        {
            return _changeToLastPage
                ?? (_changeToLastPage = new RelayCommand(
                () =>
                {
                    FrameUri = ViewModelLocator.LastPageUri;                       
                },
            () => FrameUri != ViewModelLocator.LastPageUri));                
        }
    }

我有source code on github 并使用 Win7 和 VS2017 社区。我还有其他关于程序的问题,并在 github 上打开了问题。任何帮助表示赞赏。

我的目标是拥有一些基本的 MVVMLight 程序“模板”,我可以从中提取并与像我这样的其他学习者分享...谢谢。

解决方案

  1. 将 Mode=twoway 添加到每个 @steve-teece 的绑定中。
  2. 对输出窗口进行了一些 DEBUG.writeline(根据@Michael-Randall 提出的断点建议),发现页面的 URI 不同,具体取决于它是引用回 viewmodellocater.IntroPageUri 还是由框架 FWD 调用或返回按钮。

两个 URI 结果是: /IntroPage.xaml 或 IntroPage.xaml

我的假设是“非前斜线”版本不等于带有“/”的版本。

我不确定解决此问题的最佳方法,因此我将 URI 转换为字符串,并将它们与布尔方法中的字符串 Contains 方法进行比较。

我替换了以下行:

FrameUri != ViewModelLocator.IntroPageUri

它被替换为方法调用:

CheckUri(FrameUri, ViewModelLocator.IntroPageUri)

还有,CheckUri 方法:

    private Boolean CheckUri(Uri _frameUriToCheck, Uri _vmUri)
    {
        string StringUriToCheck = _frameUriToCheck.ToString();
        string StringUriVM = _vmUri.ToString();
        System.Diagnostics.Debug.WriteLine(StringUriToCheck, "StringUriToCheck");
        System.Diagnostics.Debug.WriteLine(StringUriVM, "StringUriVM");

        if (StringUriVM.Contains(StringUriToCheck))
            { return false; }
        else
            { return true; }
    }

成功了!如果有人有更好的方法来解决它,我会全力以赴。

感谢大家的反馈!

【问题讨论】:

    标签: c# wpf mvvm viewmodel mvvm-light


    【解决方案1】:

    尝试将 XAML 更改为

    <Frame  x:Name="MainFrameDS"  Source="{Binding FrameUri, Mode=TwoWay}"  HorizontalAlignment="Left" Height="211" Margin="109,88,0,0" VerticalAlignment="Top" Width="258"/>
    

    【讨论】:

    • 认为它有很好的工作机会。试过了,canexecute 没有更新。改变的一件事是在加载第一个 IntroPage 时,Intro 按钮被禁用,但是当我尝试 Mode=TwoWay 时,所有按钮都被启用。如果我使用了一个按钮,那么该按钮就会被禁用。如果我使用框架上的 FWD 或 BACK 按钮,则所有按钮都已启用。之前的不同之处在于,按下的“最后一个”按钮在添加到双向之前总是保持禁用状态。谢谢你的建议。肯定会改变行为。
    • 我需要添加双向 - 这很有帮助,而且很好。
    • 非常感谢@Steve Teece,效果很好!
    【解决方案2】:

    首先,请确保您引用的是

    GalaSoft.MvvmLight.CommandWpf;
    

    而不是

    using GalaSoft.MvvmLight.Command;
    

    如果您的 CanExcute 没有得到评估,您可能需要通过 RaiseCanExecuteChanged 手动提出更改

    public Uri FrameUri
    {
        get
        {
            return _frameUri;
        }
        set
        {
            if(Set(FrameUriPropertyName, ref _frameUri, value))
            {
                // assuming this is the command you are having trouble with
                // this will force the command to reevaluate CanExecute
                ChangeToLastPage.RaiseCanExecuteChanged();
            }
        }
    }
    

    更新

    天哪,我什至没有注意到这一点

    public const string FrameUriPropertyName = "FrameUri";
    

    你至少需要正确设置这个

    Set(() => FrameUri, ref _frameUri, value);
    

    【讨论】:

    • 我肯定有 GalaSoft.mvvmlight.CommandWpf;我确实遇到了这个问题,当它缺少 Wpf 后缀时,canexecute 根本无法正常工作。我确实尝试添加 ChangeToLastPage.RaiseCanExecuteChanged();它并没有改变行为。我的理论是框架 BACK 和 FWD 按钮不会提高 FrameURI 属性。这仍然有意义(对我而言),因为我们明确调用了 RaiseCanExecuteChanged 方法,但它们似乎没有执行。
    • 我同意需要正确设置属性。当我尝试使用 FrameUri(类型 URI)时,出现错误并且智能感知要求输入字符串。我试图在此评论中插入屏幕截图,但不能。我会看看我是否可以将它添加到您的回复中。谢谢 - 马克
    • @FloppyDisk 但是,您需要在此处设置一些断点,在Set(() =&gt; FrameUri, ref _frameUri, value); 上设置一个,确保之后设置_frameUri,在() =&gt; FrameUri != ViewModelLocator.LastPageUri 上设置一个并让我们知道结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多