1

私は、Sourceプロパティが私のクラスのivarに設定されているListViewの設定に取り組んでいますCat

それぞれCatにオブジェクトがObservableCollectionあります。Trait

private ObservableCollection<Trait> _traits = new ObservableCollection<Trait>();

public ObservableCollection<Trait> Traits
{
get
    {
        return _traits;
    }
}

public void AddTrait(Trait t)
{
    _traits.Add(t);
    // Is this redundant? Is one better than the other?
    this.OnPropertyChanged("_traits");
    this.OnPropertyChanged("Traits");
}

public IEnumerator<Object> GetEnumerator()
{
    return _traits.GetEnumerator();
}

次に、このコレクションにSourceプロパティを割り当てます。Traits

this.CollectionViewSource.Source = CurrentCat.Traits;

これは正しく機能し、Traitオブジェクトは私のに正しく表示されますListView

問題は、この基になるコレクションを変更して_traitsも、UIが正しく更新されないことです。たとえば、これは次のとおりです。

void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
    if (this.CurrentCat != null)
    {
        this.CurrentCat.AddTrait(new Trait());
    }
}

UIですぐに効果がないようですが、次のSourceようにプロパティをリセットすると、次のようになります。

var oldSource = this.CollectionViewSource.Source;
this.CollectionViewSource.Source = null;
this.CollectionViewSource.Source = oldSource;

その後、ListView適切に更新します。ただし、アイテムの追加/削除時にUIを更新したいので、不足しているものがあるはずです。

編集:は私のXAMLファイルCollectionViewSourceに適用されています:ListView

<CollectionViewSource x:Name="CollectionViewSource" x:Key="CollectionViewSource" />

...

<ListView x:Name="ItemListView" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" ...
4

4 に答える 4

0

今は見つからないようですが、へのバインドに関する問題を覚えているようですCollectionViewSource。コードビハインドに直接バインドしてCurrentCat.Traits設定しようとthis.DataContext = thisしましたか(ここではMVVMを使用していないと想定しています)?

<ListView x:Name="ItemListView" ItemsSource="{Binding CurrentCat.Traits}" />
于 2011-12-20T05:13:54.143 に答える
0

CollectionViewSourceに直接バインドし、それを置き換えSourceて強制的に更新するのではなく、CVSのViewプロパティにバインドする必要があると思います...

<ListView x:Name="ItemListView" 
          ItemsSource="{Binding Source={StaticResource CollectionViewSource}, Path=View}" ...

CollectionViewSource.Refresh()...ソースコレクションを更新した後に呼び出します。

void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
    if (this.CurrentCat != null)
    {
        this.CurrentCat.AddTrait(new Trait());
        this.CollectionViewSource.Refresh();
    }
}

また、.NET / WPFの規則に比較的慣れていないように思われるため、いくつかの注意事項があります。

  • .NETクラスのプライベートメンバーは通常、「ivars」ではなく「fields」と呼ばれます(Objective-Cの背景?:))
  • this同じ名前のスコープ内に別の識別子がない限り、通常、クラスメンバーの前にキーワードを付けることは冗長です。
  • WPFで重要なことを行う場合は、 MVVMと関連するパターンを調べる価値があります。ビュー(XAMLオブジェクト)を可能な限り軽量で変更しやすい状態に保つのに役立ちます。

    たとえば、あなたの場合、表示したコードは、ウィンドウまたはUserControlにListViewが含まれているコードビハインドからのものであると想定しています。MVVMパターンに従うには、コレクションを含む別の「ViewModel」クラスを作成し、 (前述のようにViewプロパティを使用して)をTraits介してコレクションを公開する必要があります。CollectionViewSourceUserControlには、ViewModelのインスタンスが割り当てられDataContext、ListViewは公開されたCollectionViewにバインドできます。

于 2011-12-21T16:55:06.127 に答える
0

それでも、ObservableCollectionのみを使用して作業することができます。1つの問題がありますが、IsInDesignModeのデータが表示されません。多分将来それは改善するでしょう。

public class MainViewModel : ViewModelBase
{
...
    private ObservableCollection<PartViewModel> _parts;
    public ObservableCollection<PartViewModel> Parts
    {
        get
        {
            if (_parts == null)
            {
                _parts = new ObservableCollection<PartViewModel>();
                _parts.CollectionChanged += _parts_CollectionChanged;
            }
            return _parts;
        }
    }

    object m_ReorderItem;
    int m_ReorderIndexFrom;
    void _parts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Remove:
                m_ReorderItem = e.OldItems[0];
                m_ReorderIndexFrom = e.OldStartingIndex;
                break;
            case NotifyCollectionChangedAction.Add:
                if (m_ReorderItem == null)
                    return;
                var _ReorderIndexTo = e.NewStartingIndex;
                m_ReorderItem = null;
                break;
        }
    }

    private PartViewModel _selectedItem;
    public PartViewModel SelectedItem
    {
        get
        {
            return _selectedItem;
        }
        set
        {
            if (_selectedItem != value)
            {
                _selectedItem = value;
                RaisePropertyChanged("SelectedItem");
            }
        }
    }
   ...

    #region ViewModelBase

    public override void Cleanup()
    {
        if (_parts != null)
        {
            _parts.CollectionChanged -= _parts_CollectionChanged;
        }
        base.Cleanup();
    }

    #endregion

  }

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <CollectionViewSource x:Name="PartsCollection" Source="{Binding Parts}"/>
    </Grid.Resources>

    <ListView Margin="20" CanReorderItems="True" CanDragItems="True" AllowDrop="True" 
              ItemsSource="{Binding Source={StaticResource PartsCollection}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectionMode="Single">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
        ...
        </ListView.ItemTemplate>
    </ListView>
</Grid>
于 2013-10-28T19:38:09.793 に答える
-5

ListViewバインディングを接続して、すべてのCRUD操作で機能させることに関して私が作成したこのデモを確認してください。

http://www.flaskofespresso.com/2012/01/windows-8-metro-app-listview-binding-and-editing/

于 2012-02-10T02:01:37.573 に答える