سؤال

لدي ملف 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}}" />

وفئة الكود-Behind ، حيث حددت المرشح للحصول على نطاقات التفاصيل:

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 الحساب ، تم اختفاء المشكلة. ومع ذلك ، أنا بحاجة إليها داخل CollectionViewSource لأنني أطبق بعض التصفية له ولا يمكنني تطبيق التصفية على ObjectDataProvider.

هل يمكن لأي شخص أن يشرح لماذا يحدث هذا وكيف من المفترض أن أتصل فعليًا CollectionViewSource و ObjectDataProvider؟ شكرًا لك.

هل كانت مفيدة؟

المحلول

.

المشكلة في الكود الخاص بك هي ذلك يستخدم كل combobox نفس مثيل CollectionViewSource; ؛ هذا يعني أن المورد مع "تفاصيل" المفتاح هو مشترك من قبل الجميع ComboBox ، لذلك كلما قمت بتحديد قيمة واحدة من comboBox معين ، فإنه يحدد تلقائيًا نفس القيمة في جميع combobox. إنه لأن المجموعة الأساسية التي تتم مشاركتها ، تتتبع العنصر المحدد ، وبما أنها تتغير عند الاختيار من أحد comboBox ، فإن CollectionViewSource تخطر التغيير إلى جميع combobox.

لذلك الحل بسيط للغاية. كل ما تحتاجه لجعل مورد التفاصيل لا يمكن التلازم.

ها هو الإصلاح:

<!-- 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: Square.

س: السمة المشتركة

عند التعيين على FALSE ، يعدل سلوك WPF Resource-Recival بحيث يطلب المورد المنسوب إنشاء مثيل جديد لكل طلب بدلاً من مشاركة نفس الحالة لجميع الطلبات.

نظرًا لأن 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);

.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top