2017-07-07 7 views
0

ユーザーコントロールには、TextBoxと、Buttonという1つのユーザーコントロールがあります。 TextBoxはインデックス値をとります。MVVMのユーザーコントロールとメイン間でコマンドをリンクする方法

私のMainビューには、ファイル内のすべての行を表示する1つのリストビューがあります。 ObservableCollectionはこれにバインドしています。

私はインデックス値は(メインで)ListViewSelecedIndexインデックス値に変更する必要があり、(ユーザーコントロールに)TextBoxに入力され、表示Buttonがクリックされた場合には、必要なもの。

MVVMを使用してこれを実現するにはどうすればよいですか?

また、私が間違っている場合は、これを行う適切な方法を教えてください。ここで

は私のUserControlコード:

XAML

<UserControl.DataContext> 
    <VM:IndexView_VM ></VM:IndexView_VM> 
</UserControl.DataContext> 
<Grid Background="White"> 
    <TextBlock Margin="10,12,168,9" Text="Index : "/> 
    <TextBox Text="{Binding Index}" x:Name="TB_Index" Margin="53,11,90,8" /> 
    <Button Command="{Binding View_CMD}" x:Name="BT_View" Content="View" Margin="136,11,10,8" /> 
</Grid> 

のViewModel

public class IndexView_VM : ViewModelBase 
{ 
    public IndexView_VM() 
    { 
     View_CMD = new RelayCommand(_View_CMD); 
    } 

    int _Index; 
    public int Index 
    { 
     get { return _Index; } 
     set 
     { 
      _Index = value; 
      RaisePropertyChanged(); 
     } 
    } 

    public RelayCommand View_CMD { get; set; } 
    internal void _View_CMD(object Parameter) 
    { 
     // What to write here? 
    } 
} 

ここでメインビューです:

XAML

<UserControl.DataContext> 
     <VM:MainView_VM></VM:MainView_VM> 
    </UserControl.DataContext> 
    <Grid Background="White"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="111*"/> 
      <ColumnDefinition Width="100*"/> 
     </Grid.ColumnDefinitions> 
     <StackPanel> 
      <local:IndexView/> 
      <local:IndexView/> 
      <local:IndexView/> 
      <local:IndexView/> 
     </StackPanel> 
     <ListView ItemsSource="{Binding FileData}" x:Name="listView" Grid.Column="1" > 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Data" Width="100"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 

ビューモデル

public class MainView_VM : ViewModelBase 
{ 
    public MainView_VM() 
    { 
     ReadFile(); 
    } 

    public ObservableCollection<string> FileData { get; set; } 

    void ReadFile() 
    { 
     //I will read file here. 
    } 
} 

答えて

0

あなたがMvvmLightを使用している場合は、たとえば親に子ビューモデルからメッセージを送信するためにMessengerクラスを使用することができます。

IndexView_VM:

internal void _View_CMD(object Parameter) 
{ 
    GalaSoft.MvvmLight.Messaging.Messenger.Default.Send(_Index); 
} 

MainView_VM:

public class MainView_VM : ViewModelBase 
{ 
    public MainView_VM() 
    { 
     ReadFile(); 
     GalaSoft.MvvmLight.Messaging.Messenger.Default.Register<int>(this, index => Index = index); 
    } 

    public ObservableCollection<string> FileData { get; set; } 

    int _Index; 
    public int Index 
    { 
     get { return _Index; } 
     set 
     { 
      _Index = value; 
      RaisePropertyChanged(); 
     } 
    } 

    void ReadFile() 
    { 
     //I will read file here. 
    } 
} 

MAINVIEW:

<ListView ItemsSource="{Binding FileData}" x:Name="listView" Grid.Column="1" 
      SelectedIndex="{Binding Index}"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Header="Data" Width="100"/> 
     </GridView> 
    </ListView.View> 
</ListView> 

Messengerの詳細については、ローランBugnionのMSDNマガジンの記事を参照してください。

MVVM - MVVMでメッセンジャーや閲覧サービス:https://msdn.microsoft.com/en-us/magazine/jj694937.aspx

0

私はこの権利を理解していればわかりません。 TextBoxに入力したインデックス値を使用してListBoxの選択したアイテムを設定したいのですが、これは正しいですか?

これがある場合は、右、私は次の考慮事項を持っているものです。このシナリオでは

  1. UserControlは、おそらく過剰です。 特にをUIのどこか別の場所に再使用しない場合は、
  2. 最初に考慮する必要があるのは、TextBoxをメインビューに移動し、名前を付けて.TextプロパティをListViewSelectedIndexプロパティにバインドするだけです。

例:

intstringを変換することは、おそらく自動的に発生しませんので、(あなたが実装する必要があるでしょう)コンバータが必要とされている
<ListView SelectedIndex="{Binding ElementName=txtIndex, Path=Text, Converter={StaticResource StringToIntConverter}, UpdateSourceTrigger=PropertyChanged}" /> 

UpdateSourceTrigger=PropertyChangedは入力するとすぐにターゲットプロパティを更新し、ボタンが不要になります。

その時点で完了する必要があります。

UserControlが絶対必要な場合は、DependencyPropertyを追加してTextBoxの値を公開することができます。次に、上の例のようにPropertyにバインドできます。ここで

+0

ボタンを使用するには、 'UpdateSourceTrigger = Explicit'を設定し、そのコードの中でUpdateSourceメソッドを使用します。 –

+0

この場合、Binding(テキストボックス上のバインド)の方がより適切でしょう。 (テキストボックスは値をビューにプッシュします)。 ModeをOneWayToSourceに設定し、再びExplicit&UpdateSourceを使用します。 –

0

は、あなたが何をしたいの非常に基本的な例です。

ウィンドウXAML

<Window.Resources> 
    <local:StringToIntConverter x:Key="StringToIntConverter" /> 
</Window.Resources> 
<StackPanel> 
    <TextBlock>Select Index</TextBlock> 
    <TextBox x:Name="theTextBox" Text="{Binding SelectedIndex,ElementName=theList,Converter={StaticResource StringToIntConverter},Mode=OneWayToSource,UpdateSourceTrigger=Explicit}" /> 
    <Button Click="Button_Click">Select Now</Button> 
    <ListBox x:Name="theList"> 
     <ListBoxItem>First</ListBoxItem> 
     <ListBoxItem>Second</ListBoxItem> 
     <ListBoxItem>Third</ListBoxItem> 
    </ListBox> 
</StackPanel> 

ウィンドウ分離コード

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    theTextBox.GetBindingExpression(TextBox.TextProperty)?.UpdateSource(); 
} 

説明

ボタンをクリックして、テキストボックスからリストにインデックスを設定するよう求めていました。私たちは、設定のカップルと、選択したインデックスにテキストボックスをバインド:

  • 出典:SelectedIndexを
  • のElementName:リスト/ターゲットUIエレメント
  • コンバータ:intに文字列から取得するために必要な(私は上に書きました自分自身)
  • モード:私たちは、自動更新への結合を、私たちは自分自身の
  • これを行うにはしたくしたくない:OneWayToSource、我々はリストではなく
  • UpdateSourceTrigger他の方法でラウンドに値を送るだけにテキストボックスを強制

バインディングを更新するには、ボタンのクリックイベントを使用します。

ビューモデルはどうですか? 操作は表示のみの操作です.ViewModelはそれについて何も知る必要がないので、操作から除外してください。それで、私はCommandBindingを使用していないのです。

おっと、あなたがユーザーコントロールでこれを入れたいなら、私はあなたがすべてでのViewModelを作成していないことを示唆しているUserControl 忘れてしまいました。また、ユーザーコントロールでは、DataBindingは必要ありません。外部でのみ必要です。それをシンプルに保つ:

UserControlのXAML

<TextBlock>Select Index</TextBlock> 
<TextBox x:Name="theTextBox" /> 
<Button Click="Button_Click">Select Now</Button> 

UserControlの分離コード

public int Index 
{ 
    get { return (int)GetValue(IndexProperty); } 
    set { SetValue(IndexProperty, value); } 
} 

public static readonly DependencyProperty IndexProperty = 
     DependencyProperty.Register("Index", typeof(int), typeof(ListViewIndexSelectorControl), new PropertyMetadata(0)); 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if(int.TryParse(theTextBox.Text, out int result)) 
    { 
     Index = result; 
    } 
} 

メインウィンドウの使用XAML

<local:ListViewIndexSelectorControl Index="{Binding SelectedIndex,ElementName=theList,Mode=OneWayToSource}" /> 
<ListBox x:Name="theList"> 
    <ListBoxItem>First</ListBoxItem> 
    <ListBoxItem>Second</ListBoxItem> 
    <ListBoxItem>Third</ListBoxItem> 
</ListBox> 

後でViewModelが必要な場合は、ViewのコンストラクタでDataContext = this;を設定するか、XAML要素にNameを使用し、ElementNameでDataContextをバインドするだけで、ViewModelとして単純なコントロールを使用することもできます。

関連する問題