mvvmlight wpf如何提高帧源属性wpf c#

时间:2018-02-10 23:18:10

标签: c# wpf mvvm viewmodel mvvm-light

(见下面的解决方案)

苦苦挣扎学习MVVMLight和WPF。很高兴获得带有3个按钮的框架的页面导航,并且还获得了按钮的CanExecute RelayCommand功能。

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

这里的正确行为:

CANEXECUTE WORKS WELL HERE!

按下框架BACK按钮时,此处无法正常工作。页面更改(正常),但按钮Middle canexecute未正确更新。请参阅下面的属性和中继命令。

CanExecute not working

MVVMINPCPROPERTY代码段

    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 for Frame

    <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社区。我还有其他问题w / program并在github上打开了问题。任何帮助表示赞赏。

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

解决方案

  1. 将模式= twoway添加到每个@ steve-teece的绑定。
  2. 将一些DEBUG.writeline(每个@ Michael-Randall的断点建议)输出到输出窗口,发现页面的URI不同,具体取决于它是否返回到viewmodellocater.IntroPageUri或由帧FWD调用或后退按钮。
  3. 两个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; }
        }
    

    那很有效!如果有人有更好的解决方法,我会全力以赴。

    感谢大家的反馈!

2 个答案:

答案 0 :(得分:1)

尝试将XAML更改为

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

答案 1 :(得分:0)

首先,确保您引用

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);