0

ここでまた昨日とよく似た質問をします。MVVM パターンによりよく従うために、プロジェクトをリファクタリングしました。昨日のようにバインディングが機能しなくなりました。ドックパネルの可視性をボタンにバインドしようとしています。これが私のコードの一部です:

ビューモデル:

public class SelectWaferButtonViewModel : INotifyPropertyChanged
{
    private bool isClicked;

    public SelectWaferButtonViewModel()
    {
        isClicked = false;
    }

    public bool IsControlVisible
    {
        get
        {
            return isClicked;
        }
        set
        {
            isClicked = value;
            OnPropertyChanged("IsControlVisible");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnButtonClick()
    {
        if (isClicked)
        {
            IsControlVisible = false;
        }
        else
        {
            IsControlVisible = true;
        }
    }
    protected virtual void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

XAML:

<Window.Resources>
     <local:BoolToVisibilityConverter x:Key="BoolToVisConverter"/>
     <local:SelectWaferButtonViewModel x:Key="SelectWaferButton" />
     <local:WaferTrackerWindowViewModel x:Key="WindowViewModel" />
</Window.Resources>
<DockPanel
     Name="tvwDockPanel"
     DataContext="{StaticResource SelectWaferButton}"
     Width="225"
     Visibility="{Binding IsControlVisible, Mode=TwoWay, 
                  FallbackValue=Collapsed, 
                  Converter={StaticResource BoolToVisConverter}}"
     DockPanel.Dock="Left">
 </DockPanel>

私のBoolToVisConverter

public class BoolToVisibilityConverter : IValueConverter
{
    public BoolToVisibilityConverter() { }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool bValue = (bool) value;
        if (bValue)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Visibility visibility = (Visibility) value;
        if (visibility == Visibility.Visible)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

昨日に似た質問で申し訳ありませんが、私はWPFに慣れていないので、このMVVMのことで苦労しています。どんな助けでも大歓迎です。

  • よろしくお願いします。

編集: さらに参照するための追加のコードスニペットを次に示します。

public class WaferTrackerWindowViewModel :INotifyPropertyChanged
{
    private SelectWaferButtonViewModel btnSelectWaferViewModel;
    public event PropertyChangedEventHandler PropertyChanged;
    private DelegateCommand exitCommand;
    private DelegateCommand expandPanelCommand;
    private DelegateCommand selectWaferCommand;

    public WaferTrackerWindowViewModel()
    {
        this.InstantiateObjects();
        initThread.RunWorkerAsync();
    }

    public string SelectedWafer
    {
        get
        {
            return selectedWafer;
        }
        set
        {
            selectedWafer = value;
        }
    }
    public ICommand ExitCommand
    {
        get
        {
            if (exitCommand == null)
            {
                exitCommand = new DelegateCommand(Exit);
            }
            return exitCommand;
        }
    }
    public ICommand ExpandPanelCommand
    {
        get
        {
            if (expandPanelCommand == null)
            {
                expandPanelCommand = new DelegateCommand(ExpandPanel);
            }
            return expandPanelCommand;
        }
    }
    public ICommand SelectWaferCommand
    {
        get
        {
            if (selectWaferCommand == null)
            {
                selectWaferCommand = new DelegateCommand(SelectWafer);
            }
            return selectWaferCommand;
        }
    }

    private void InstantiateObjects()
    {
        btnSelectWaferViewModel = new SelectWaferButtonViewModel();
        initThread = new BackgroundWorker();
    }
    private void ExpandPanel()
    {
        btnSelectWaferViewModel.OnButtonClick();
    }
    private void SelectWafer()
    {
       //Does Nothing Yet
    }
    private void Exit()
    {
        Application.Current.Shutdown();
    }
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private void InitThread_DoWork(object sender, DoWorkEventArgs e)
    {
        TreeViewPresenter tvwPresenter = new TreeViewPresenter();
        tvwPresenter.WaferList = DataLibrary.GetWaferList();
    }
    private void InitThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        tvwPresenter.TreeView.DataContext = tvwPresenter.ProcessesAndWafers;
        tvwPresenter.WaferListCache = tvwPresenter.ProcessesAndWafers;
        tvwPresenter.ProcessArray = tvwPresenter.WaferListCache.ToArray();
    }
}

「パネルを展開」ボタンがクリックされると、ExpandPanelコマンドが呼び出され、この同じクラスのメソッド「private void ExpandPanel()」に実行がルーティングされます。次に、メソッドでオブジェクトのメソッドをExpandPanel()呼び出し、プロパティを変更します。この変更は、バインドされたドック パネルに反映されるはずですが、これは行われていません。OnButtonClick()btnSelectWaferViewModelIsControlVisible

カイル

4

2 に答える 2

2

(1) ViewModel は、Window.DataContextセクションではなく、Window.Resourcesセクションにある必要があります。

(2)ビューモデルで、IsControlVisibleプロパティをSystem.Windows.Visibilityブール値ではなく にすると、コンバーターは必要ありません。

(3) を起動する方法が見当たらず、インターフェイスOnButtonClickで設定する必要がありICommandます。

(4)バインド先のプロパティは定義上一方向であるConvertBackため、実装する必要はありません。Visibilityユーザーが を に設定する方法はありません。visibilityfalse

IsClicked(5) accessor と accessor を混在させないでくださいIsControlVisibleIsClicked誤ってアクティブ化しない設定を行うリスクがあるため、MVVM では常にアクセサーを使用してくださいOnPropertyChanged

全体として、あなたはかなり近いです。「出力」ウィンドウに注意してください。何らかの理由でバインディングが失敗しているかどうかがわかります。でもまあ、ちょっと待って!

于 2013-02-05T20:30:04.483 に答える
1

したがって、これを行うと:

<Window.Resources>
    <local:SelectWaferButtonViewModel x:Key="SelectWaferButton" />
</Window.Resources>

WPF は の新しいインスタンスを作成し、そのSelectWaferButtonViewModelリソースに追加します。DataContext次に、 キーを使用してを設定して、これにバインドしStaticResourceます。

ただし、SelectWaferButtonViewModelコード ビハインドで別のインスタンスを作成し、コマンドをそのインスタンスにリンクする場合、それは同じインスタンスではないため、このバインドされていないインスタンスのプロパティを変更しても UI には影響しません。それを回避する方法はいくつかあります。次のように、a) コード ビハインドで単一SelectWaferButtonViewModelのプロパティを作成し、XAML でそれにバインドするか、b)SelectWaferButtonViewModel現在持っているように XAML で宣言し、コード ビハインドでそのインスタンスを取得します。

SelectWaferButtonViewModel swbvm = (SelectWaferButtonViewModel)this.FindResource("SelectWaferButton");

編集btnSelectWaferViewModel:したがって、最後の編集を確認した後、a) を使用する場合は、プロパティとして公開し、WaferTrackerWindowViewModelウィンドウの DataContext をインスタンスに設定してそのプロパティにバインドすることをお勧めしWaferTrackerWindowViewModelます。したがって、次のような結果になります。

<DockPanel
    Name="tvwDockPanel"
    Width="225"
    Visibility="{Binding MyButton.IsControlVisible, 
        Converter={StaticResource BoolToVisConverter}}"
    DockPanel.Dock="Left">
</DockPanel>

と:

public class WaferTrackerWindowViewModel :INotifyPropertyChanged
{
    private SelectWaferButtonViewModel btnSelectWaferViewModel;
    public SelectWaferButtonViewModel MyButton 
    {
        get { return btnSelectWaferViewModel; }
        set
        {
            btnSelectWaferViewModel = value;
            OnPropertyChanged("MyButton");
        }
    }
    //......
于 2013-02-05T21:24:43.930 に答える