2017-10-23 6 views
0

私は、ユーザーにアセットのリストを表示し、リストからアセットを削除することを許可するビュー(「Familify」と呼ばれる)を作成しています。アセットはViewModel内のObservableCollectionに格納されているため、削除するコマンドは単にアセットオブジェクトを取り出してコレクションから削除します。私は問題を '削除'機能の作業を取得しています。アイデアは、ボタンをクリックすると、リストから資産を取り除くことであるx:データテンプレートとは異なるデータ型でバインドする

Familify.xaml

<ListView 
    ItemsSource="{Binding Assets}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="80px" /> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="150px" /> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="60px" /> 
       </Grid.ColumnDefinitions> 
       <TextBlock 
        Grid.Column="0" 
        Text="{Binding number}" FontFamily="Consolas"/> 
       <TextBlock 
        Grid.Column="1" 
        Text="{Binding type}"/> 
       <TextBlock 
        Grid.Column="2" 
        Text="add binding here"/> 
       <TextBlock 
        Grid.Column="3" 
        Text="add binding here"/> 
       <Button 
        Command="{x:Bind ViewModel.RemoveAssetCommand}" 
        CommandParameter="{Binding}" 
        Content="&#xE894;" 
        FontFamily="Segoe MDL2 Assets" 
        Grid.Column="4"> 
       </Button> 
      </Grid> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

Familify.xaml.cs

namespace asset_manager.Views 
{ 
    public sealed partial class Familify : UserControl 
    { 
     FamilifyViewModel ViewModel { get; set; } 

     public Familify() 
     { 
      this.InitializeComponent(); 
      DataContextChanged += (s, e) => 
      { 
       ViewModel = DataContext as FamilifyViewModel; 
      }; 
     } 
    } 
} 

:ここではXAMLと分離コードであります。 (ただ、numbertypeなどを示す正常な結合に注意することは正しく機能している。)私の考えでは、これまで:

  1. RemoveAssetCommandは、ページのビューモデルに保存されているアクセスするためにbindingを使用するようにしてください。しかし、私は仕事に先祖の結合を得ることができませんでした(findAncestorがUWPにおけるものではありませんので、すなわちXAML階層内の要素上位までのデータコンテキストを見つけようとして動作しませんでした。)
  2. x:Bindのように見えましたそれはプロパティへの明示的なパスを使用するためです。だから、もし私がViewModelを私のコードの裏に宣言すれば、私はx:Bind ViewModel.propertyを使うことができました。すべての井戸と良い。私はちょうどそれを行い、intellisenseは私がViewModel.RemoveAssetCommandにアクセスすることを許可しました。
  3. しかし、私はエラーno DataType defined for DataTemplateを得るため、これはうまくいかなかった。これは意味があるので、私は2つのことを試みました。
  4. x:DataType="Models:Asset"(上記のDataTemplateタグ)は、データテンプレートに表示されているモデルなので、最初に試しました。もちろん、コマンドはモデルで宣言されておらず、View Modelで宣言されているため、機能しませんでした。
  5. 代わりにx:DataType="ViewModels:FamilifyViewModel"を試してみましたが、私はちょうどx:Bindを使用することができます。しかし、タイプAssetのオブジェクトをFamilifyViewModelにキャストできないというエラーが発生しました。オブジェクトがこのデータテンプレートに渡されるのはAssetなので、意味があります。

私がx:Bindが働くと思った全体の理由は、コードビハインドのViewModelから直接プロパティにアクセスすることができたからです。

ViewModelの基本レベルのプロパティ(この場合はPrismコマンド)にアクセスするには、データテンプレート内でx:Bindを使用することは可能ですか? 2)この機能を実装するより良い方法はありますか?

答えて

0

データテンプレート内でViewModelのベースレベルプロパティ(この場合はプリズムコマンド)にアクセスすることは可能ですか?

あなたは基本レベルにアクセスしたい場合は、[はい、あなたは次のようにボタンのDataContextのを再割り当てすることができます

<Button DataContext="{Binding ElementName=Familily, Path=DataContext}"/> 

FamilyUserControlの名前です。

この機能を実装するには良い方法がありますか?

ViewModelcommadを置き、上記のようにボタンをバインドします。ボタンのバインド項目はファミリDataContextになります。したがって、ViewModelで削除アクションを直接呼び出すことはできませんでした。

この機能を実装するベストプラクティスは、をAssetクラスに入れることです。 ItemsSourceListViewButtonCommandParameterとしてください。

<Button 
    Command="{Binding RemoveAssetCommand}" 
    CommandParameter="{Binding ElementName=MyListView, Path=ItemsSource}" 
    Content="&#xE894;" 
    FontFamily="Segoe MDL2 Assets" 
    Grid.Column="4"> 
</Button> 

Asset.cs

public class Asset 
{ 
    public string number { get; set; } 
    public string type { get; set; } 
    public ICommand RemoveAssetCommand 
    { 
     get 
     { 
      return new CommandHandler<ObservableCollection<Asset>>((item) => this.RemoveAction(item)); 
     } 
    } 
    private void RemoveAction(ObservableCollection<Asset> items) 
    { 
     items.Remove(this); 
    } 
} 

ViewModel.cs

public class FamilifyViewModel 
{ 
    public ObservableCollection<Asset> Assets = new ObservableCollection<Asset>(); 
    public FamilifyViewModel() 
    { 
     Assets.Add(new Asset { number = "100001", type = "hello" }); 
     Assets.Add(new Asset { number = "100001", type = "hello" }); 
     Assets.Add(new Asset { number = "100001", type = "hello" }); 
     Assets.Add(new Asset { number = "100001", type = "hello" }); 
    }   
} 

enter image description here

+0

これは完璧です、ありがとうございました! –

関連する問題