0

Windows Phone 8 アプリがあり、 というRelayCommandインスタンスがありDiscoverExpansionModulesCommandます。Commandプロパティが にバインドされたボタンがありますDiscoverExpansionModulesCommand。アプリが最初に読み込まれると、ボタンが適切に有効または無効になります。ただし、ページ上でコマンドを実行できるかどうかを変更したい場合、メソッドはCanExecuteDiscoverExpansionModulesCommand()適切に起動し、適切な true または false 値を返しますが、ボタンには反映されません。ボタンの UI が更新されないのはなぜですか? この問題に関する別の記事をここで見つけましたhttp://social.msdn.microsoft.com/Forums/en-US/silverlightarchieve/thread/48a341e4-f512-4c33-befd-b614404b4920/

私のビューモデル:

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using MAL.Portable.Commands;
using MAL.Portable.Message;
using MAL.Portable.Model;
using System;
using System.Collections.Generic;
using System.Windows.Input;

namespace MAL.Portable.ViewModel
{
    public class SettingsViewModel : ViewModelBase
    {
        // Define an observable collection property that controls can bind to.
        private List<Setting> settings;
        private String controllerUrl;
        private String controllerPort;
        private String temperature;
        private Wifi wifi;
        private Boolean connected;
        private Boolean checkingConnection;


        public SettingsViewModel()
        {
            DiscoverExpansionModulesCommand = new RelayCommand(OnDiscoverExpansionModules, CanExecuteDiscoverExpansionModulesCommand);

            Messenger.Default.Register<RetrieveSettingsMessage>
            (
                 this, (action) => RetrievedListsMessage(action)
            );

            Messenger.Default.Send<GetSettingsMessage>(new GetSettingsMessage());
        }

        public ICommand DiscoverExpansionModulesCommand
        {
            get;
            private set;
        }

        public String ConnectionStatus
        {
            get
            {
                if (checkingConnection) 
                    return "checking";
                else
                    return connected ? "connected" : "not connnected";
            }
        }

        private Boolean CanExecuteDiscoverExpansionModulesCommand()
        {
            return connected;
        }

        private void OnDiscoverExpansionModules()
        {

        }

        private void CheckConnection()
        {
            wifi = null;
            if (!String.IsNullOrWhiteSpace(ControllerUrl) && !String.IsNullOrWhiteSpace(ControllerPort) && !checkingConnection)
            {
                checkingConnection = true;
                wifi = new ReefAngelWifi(controllerUrl, controllerPort);
                wifi.TestConnectionComplete += wifi_TestConnectionComplete;
                wifi.RequestFail += wifi_RequestFail;
                wifi.BeginTestConnection();
            }
        }

        private void wifi_RequestFail(object sender, RequestExceptionEventArgs e)
        {
            connected = false;
            checkingConnection = false;
            RaisePropertyChanged("ConnectionStatus");
        }

        private void wifi_TestConnectionComplete(object sender, TestConnectionEventArgs e)
        {
            connected = e.TestSuccessful;
            checkingConnection = false;
            DiscoverExpansionModulesCommand.CanExecute(null);
            RaisePropertyChanged("ConnectionStatus");
            RaisePropertyChanged("DiscoverExpansionModulesCommand");
        }

        private object RetrievedListsMessage(RetrieveSettingsMessage action)
        {
            settings = action.Settings;
            CheckConnection();
            return null;
        }

        private String GetStringValue(String key)
        {
            if (settings == null) return String.Empty;
            var item = settings.Find(x => x.Key == key);
            if (item == null) return String.Empty;
            else return item.Value;
        }

        private Boolean GetBooleanValue(String key)
        {
            if (settings == null) return false;
            var item = settings.Find(x => x.Key == key);
            if (item == null) return false;
            else return Boolean.Parse(item.Value);
        }
    }
}

そしてXAML

<phone:PhoneApplicationPage 
    xmlns:ReefAngel="clr-namespace:MAL.WindowsPhone8"  
    xmlns:Controls="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform.WP8"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:telerikPrimitives="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Primitives"
    x:Class="MAL.WindowsPhone8.ReefAngel.SettingsPage"
    xmlns:converter="clr-namespace:MAL.WindowsPhone8.Converters"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    DataContext="{Binding Settings, Source={StaticResource Locator}}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.Resources>
        <converter:BooleanToStringConverter x:Key="temperatureConverter" TrueString="Celsius" FalseString="Fahrenheit" />
        <converter:BooleanToStringConverter x:Key="timeFormatConverter" TrueString="24 hour" FalseString="12 hour" />
        <converter:BooleanToStringConverter x:Key="dateFormatConverter" TrueString="dd/mm/yyyy" FalseString="mm/dd/yyyy" />
    </phone:PhoneApplicationPage.Resources>

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" >
        <phone:Pivot Title="{Binding LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}, StringFormat='\{0\} Settings'}">
            <phone:PivotItem Header="connection">
                <Grid>
                    <StackPanel Margin="12,0,0,0">
                        <TextBlock Margin="0,20,0,0" TextWrapping="Wrap" Text="Reef Angel Wifi Address"/>
                        <TextBox Height="72" TextWrapping="Wrap" Text="{Binding ControllerUrl, Mode=TwoWay}"/>
                        <TextBlock Margin="0,20,0,0" TextWrapping="Wrap" Text="Reef Angel Wifi Port"/>
                        <TextBox Height="72" TextWrapping="Wrap" Text="{Binding ControllerPort, Mode=TwoWay}"/>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Margin="0,20,0,0" TextWrapping="Wrap" Text="Reef Angel Wifi Status : "/>
                            <TextBlock Margin="0,20,0,0" TextWrapping="Wrap" Text="{Binding ConnectionStatus, Mode=OneWay}"/>
                        </StackPanel>

                    </StackPanel>
                </Grid>
            </phone:PivotItem>
            <phone:PivotItem Header="expansion">
                <Grid>
                    <Button Content="Discover Expansion Modules" x:Name="DiscoverButton" Command="{Binding DiscoverExpansionModulesCommand, Mode=OneWay}" />
                </Grid>
            </phone:PivotItem>

        </phone:Pivot>
    </Grid>

</phone:PhoneApplicationPage>

MVVM Light Portable Class Libraries を使用しています。

4

2 に答える 2

7

RelayCommand.RaiseCanExecuteChanged()メソッド内で評価する条件が変更されたときに呼び出す必要がありますCanExecute

編集

    private void wifi_RequestFail(object sender, RequestExceptionEventArgs e)
    {
        connected = false;
        checkingConnection = false;
        RaisePropertyChanged("ConnectionStatus");
        DiscoverExpansionModulesCommand.RaiseCanExecuteChanged();
    }

    private void wifi_TestConnectionComplete(object sender, TestConnectionEventArgs e)
    {
        connected = e.TestSuccessful;
        checkingConnection = false;
        DiscoverExpansionModulesCommand.CanExecute(null);
        RaisePropertyChanged("ConnectionStatus");
        RaisePropertyChanged("DiscoverExpansionModulesCommand");
        DiscoverExpansionModulesCommand.RaiseCanExecuteChanged();
    }

指定された CanExecute メソッドを再実行するよう RelayCommand に指示するだけなので、ループは発生しません。あなたの場合、これはプロパティCanExecuteDiscoverExpansionModulesCommandが読み取られることを意味するだけです。

于 2013-03-27T11:27:38.133 に答える
1

クロススレッドの問題のようです。また、PCL で Dispatcher を呼び出す方法を理解するのは困難でしたが、ここで見つけました: ポータブル クラス ライブラリから UI スレッドを更新する

于 2013-03-27T16:49:10.613 に答える