WPFデータバインディング:CollectionViewSourceおよびObjectDataproviderの問題
-
29-09-2019 - |
質問
mainWindow.xamlファイルがあります:
<Window.Resources>
<CollectionViewSource x:Key="cvs"
Source="{Binding Source={StaticResource ResourceKey=DetailsCollection}}" />
<CollectionViewSource x:Key="DetailScopes">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
<DataTemplate x:Key="AccountDetail"
DataType="{x:Type entities:AccountDetail}">
<DockPanel>
<ComboBox
DockPanel.Dock="Left"
ItemsSource="{Binding Source={StaticResource ResourceKey=DetailScopes}}"
SelectedItem="{Binding Path=Scope}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Converter={StaticResource DetailScopeConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Text="{Binding Path=Value}" />
</DockPanel>
</DataTemplate>
</Window.Resources>
...
<ListBox
ItemTemplate="{StaticResource ResourceKey=AccountDetail}"
ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}" />
そして、そのコードビハインドクラスでは、詳細スコープのフィルターを定義しました。
public class MainWindow
{
public MainWindow()
{
CollectionViewSource detailScopes;
InitializeComponent();
// Attach filter to the collection view source
detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);
private void DetailScopesFilter(object sender, FilterEventArgs e)
{
DetailScope scope;
scope = (DetailScope)e.Item;
if (scope == DetailScope.Private ||
scope == DetailScope.Business)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
}
次に、があります AccountDetail
クラス:
public class AccountDetail
{
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public DetailScope Scope
{
get { return scope; }
set { scope = value; }
}
private string value;
private DetailScope scope;
}
最後に、列挙:
public enum DetailScope
{
Private,
Business,
Other
}
コードを実行すると、アカウントの詳細が多数入力されたリストボックスがあります。それぞれに、選択したスコープと適切な値のテキストボックスを備えた独自のコンボボックスがあります。問題は、コンボボックス内のすべての選択された値が、最後に入力された詳細のスコープセットと一致し、それらがすべて同じアカウントの詳細にバインドされているかのように、それらすべてを更新するコンボボックス値を変更することです。
私が取り出すとき ObjectDataProvider
から CollectionViewSource
詳細なコープとそれをコンボボックスに直接バインドします ItemsSource
の中に DataTemplate
accountdetail、問題はなくなりました。ただし、内部で必要です CollectionViewSource
私はそれにいくつかのフィルタリングを適用していて、フィルタリングを適用できないからです ObjectDataProvider
.
なぜこれが起こっているのか、そして私が実際に接続することになっているのはなぜかを説明してもらえますか CollectionViewSource
と ObjectDataProvider
?ありがとうございました。
解決
.
コードの問題はそれです すべてのコンボボックスは、CollectionViewSourceの同じインスタンスを使用しています;つまり、キー「DetailingCopes」を備えたリソースは すべてが共有します コンボボックスは、特定のコンボボックスから1つの値を選択するたびに、すべてのコンボボックスで同じ値を自動的に選択します。 それは、共有されている基礎となるコレクションが選択したアイテムを追跡し、1つのコンボボックスから選択すると変更されるため、CollectionViewSourceはすべてのコンボボックスの変更に通知するためです.
そのため、ソリューションは非常に簡単です。詳細コープリソースを作成するために必要なすべて 恥ずかしくない.
これが修正です:
<!-- Please note this x:Shared="False" just after x:Key="DetailsScopes" --->
<CollectionViewSource x:Key="DetailScopes" x:Shared="False">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
それがあなたの問題を解決することを願っています!
ただし、このソリューションは別の問題を引き起こします。 MSDNから何かを引用させてください。そうすれば、X:Sharedが何をするかを理解できます。
X:共有属性
falseに設定した場合、WPFリソース - レトリエバルの動作を変更して、属性リソースのリクエストが 各リクエストの新しいインスタンスを作成します すべてのリクエストに対して同じインスタンスを共有する代わりに。
x:共有原因は、アクセスしようとするたびにリソースの新しいインスタンス(新しいコピー)を作成するため、フィルターハンドラーメソッドは、すべてではなく、コードビハインドで取得するインスタンスにのみ添付されます。インスタンス。
したがって、ハンドラーを適切に動作させるには、XAML自体からハンドラーを添付する必要があります。
<!-- Now please note Filter="DetailsScopesFilter" --->
<CollectionViewSource x:Key="DetailScopes" x:Shared="False" Filter="DetailScopesFilter">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
それがあなたのすべての問題を解決することを願っています。まだ直面している場合は教えてください。:-)
ちなみに、次のコードビヒンドはもう必要ありません。削除してください。
// Attach filter to the collection view source
detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);
.