xamlでusercontrolsをバインドする方法は?

MainWindowには、データグリッドと「フィルタパネル」があります。フィルタパネルは、ユーザ入力(ボタンクリック)によって変更することができます。私はデータバインディングでそれを達成しようとします。私が直面している問題は、フィルタパネル(ユーザコントロール)がロードされていないか、リフレッシュされていないことです。

メインウィンドウxaml:

 
    
        
        
    
     
    

    <button Content="PersonFilter" Height="23" HorizontalAlignment="Left" Margin="23,268,0,0" Name="buttonPersonFilter" VerticalAlignment="Top" Width="75" Click="buttonPersonFilter_Click" />
    <button Content="ProjectFilter" Height="23" HorizontalAlignment="Left" Margin="132,268,0,0" Name="buttonProjectFilter" VerticalAlignment="Top" Width="75" Click="buttonProjectFilter_Click" />


コードの背後にある:

 private ViewModel _viewModel;
    public MainWindow()
    {
        _viewModel = new ViewModel(new DataProvider());
        DataContext = _viewModel;
        _viewModel.PropertyChanged += _viewModel.SetFilterType;
        InitializeComponent();
    }


    private void buttonProjectFilter_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.OverviewType = OverviewType.Project;
    }

    private void buttonPersonFilter_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.OverviewType = OverviewType.Person;
    }

最初のユーザーコントロール:


    

このユーザーコントロールの背後にあるコードは次のとおりです。

 public DateTime FundingTo { get; set; }
 public ProjectFilter()
    {
        FundingTo = DateTime.Now;

        InitializeComponent();
    }

他のユーザーコントロール:単純にTextBoxとButtonが含まれていますが、簡単にするために、後ろにコードを追加しませんでした。

MainWindowのViewModel:

public class ViewModel  : INotifyPropertyChanged
{
    private UserControl _userControl;

    public UserControl UserControl
    {
        get { return _userControl; }
        set
        {
            if (_userControl == value)
            {
                return;
            }
            OnPropertyChanged("UserControl");
            _userControl = value;
        }
    }

    private OverviewType _overviewType = OverviewType.None;
    public OverviewType OverviewType
    {
        get { return _overviewType; }
        set
        {
            if (_overviewType == value)
            {
                return;
            }
            OnPropertyChanged("OverviewType");
            _overviewType = value;
        }
    }

    private ObservableCollection _overviewableItems;
    public ObservableCollection OverviewableItems
    {
        get { return _overviewableItems; }
        set
        {
            if (_overviewableItems == value)
            {
                return;
            }
            _overviewableItems = value;
        }
    }

    private readonly DataProvider _dataProvider;

    public event PropertyChangedEventHandler  PropertyChanged;

    public ViewModel(DataProvider dataProvider)
    {
        _dataProvider = dataProvider;
    }

    public void SetFilterType(object sender, EventArgs eventArgs)
    {

        switch (_overviewType)
        {
            case OverviewType.Project:
                _userControl = new ProjectFilter();
                break;
            case OverviewType.Person:
                _userControl = new PersonFilter();
                break;
        }
    }

    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged == null)
            return;

        var eventArgs = new PropertyChangedEventArgs(name);
        PropertyChanged(this, eventArgs);
    }  
}

私はEnum OverviewTypeをNone、Project、Personの値で持っています。

プロパティ変更イベントは正常に発生しましたが、ユーザーコントロールは更新されません。誰も私を魅了することはできますか?私のソリューションの欠陥はどこにありますか?

そして私が持っているもう1つの質問は、どのように私はusercontrolsからmainwindow viewmodelに通信することができますか?外国為替:そのフィルタに従ってデータグリッドを変更する必要があります。

どんな助けでも大歓迎です。乾杯!

0

2 答え

ここにはさまざまな問題があります。

  • クレメンスは言ったように、値が更新されたらあなたのイベントを起こさなければなりません。しかし、ここでの主な問題ではありません。

  • 第2の問題:新しい usercontrol のプライベートメンバーに影響を与えているため、あなたは完全にあなたの財産を迂回しています。

置換

_userControl = new ProjectFilter();

によって

this.UserControl = new ProjectFilter();
  • 3番目の問題は、あなたの質問に直接関係していませんが、実際には最大の問題です:あなたはアーキテクチャ設計上の問題を持っています。 アンチパターンである UserControl をビューモデルに公開していますをご覧ください。あなたのビューモデルはビューの何かを知ることはできませんので、ビュー内のコントロールへの参照はしないでください。あなたが書いたバインディングの代わりに、viewmodelからイベントを起動し、ビュー内にイベントハンドラを追加することで、ユーザコントロールを更新するビューにすることができます。
4
追加された
@ JahManCanバインディングオプションは動作しますが、MVVMパターンではありません。 2番目のオプションははるかに良いIMOです(ビューコードは、ビューに純粋に関連するものはOKです)。
追加された 著者 ken2k,
あなたの言ってる事がわかります。しかし、拘束力のある選択肢に行くことは可能ですか?または、このように追加する方が良いでしょうか? stackPanelFilter.Children.Clear(); stackPanelFilter.Children.Add(UserControl); - 後ろのコードを見る
追加された 著者 JahManCan,

プロパティのバッキングフィールドを変更した後、PropertyChanged 起動させてください:

public UserControl UserControl
{
     get { return _userControl; }
     set
     {
         if (_userControl != value) 
         {
            _userControl = value;             //first
             OnPropertyChanged("UserControl");//second
         }
     } 
}

OverviewType と同様です。

4
追加された
あなたはこれについて正しいですが、これはImが直面している問題を解決するものではありません。 Ken2kの解決策を見ていきます。
追加された 著者 JahManCan,