0

У меня есть пользовательский контроль, он наследует элемент управления ListBox, в котором я добавил два параметра DependencyProperty для ввода ввода, а другой - для отправки обработанного вывода посредством привязки.Как вернуть значение через свойство Dependency в двухстороннем привязке WPF Custom Control C#?

Ниже пользовательского элемента управления BListBox наследуется ListBox: - C# Coding

public class BListBox : ListBox 
{ 
    static BListBox() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(BListBox), new FrameworkPropertyMetadata(typeof(ListBox))); 
    } 

    public static readonly DependencyProperty FilterKeyProperty = 
    DependencyProperty.Register("FilterKey", typeof(string), typeof(BListBox), new UIPropertyMetadata(null)); 

    public string FilterKey 
    { 
     get { return (string)GetValue(FilterKeyProperty); } 
     set { SetValue(FilterKeyProperty, value); } 
    } 

    public static readonly DependencyProperty FilterDictionaryProperty = 
     DependencyProperty.Register("FilterDictionary", typeof(Dictionary<string, ObservableCollection<CheckedListItem<string>>>), typeof(BListBox), new UIPropertyMetadata(null)); 

    public Dictionary<string, ObservableCollection<CheckedListItem<string>>> FilterDictionary 
    { 
     get { return (Dictionary<string, ObservableCollection<CheckedListItem<string>>>)GetValue(FilterDictionaryProperty); } 
     set { SetValue(FilterDictionaryProperty, value); } 
    } 

    public static readonly DependencyProperty InputSourceProperty = 
    DependencyProperty.Register("InputSource", typeof(IEnumerable), typeof(BListBox), new UIPropertyMetadata(null)); 

    public IEnumerable InputSource 
    { 
     get { return (IEnumerable)GetValue(InputSourceProperty); } 
     set { SetValue(InputSourceProperty, value); } 
    } 

    public static readonly DependencyProperty OutputSourceProperty = DependencyProperty.Register("OutputSource", 
                             typeof(IEnumerable), 
                             typeof(BListBox), 
                             new FrameworkPropertyMetadata(
                              null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 

    public IEnumerable OutputSource 
    { 
     get { return (IEnumerable)GetValue(OutputSourceProperty); } 
     set { SetValue(OutputSourceProperty, value); } 
    } 

    ObservableCollection<dynamic> InputSourceCollection = new ObservableCollection<dynamic>(); 
    ObservableCollection<dynamic> OutputSourceCollection = new ObservableCollection<dynamic>(); 
    ObservableCollection<dynamic> SourceCollection = new ObservableCollection<dynamic>(); 

    public void FilterResult(CheckedListItem<string> curFilter) 
    { 
     ObservableCollection<CheckedListItem<string>> CustomerFilters = ItemsSource != null ? ItemsSource as ObservableCollection<CheckedListItem<string>> : new ObservableCollection<CheckedListItem<string>>(); 

     if (CustomerFilters.Count > 0) 
     { 
      if (InputSourceCollection.Count ==0) 
       InputSourceCollection = IEnumeratorToObservableCollection(InputSource); 

      OutputSourceCollection = IEnumeratorToObservableCollection(OutputSource); 

      if (FilterDictionary.Remove(FilterKey)) 
       FilterDictionary.Add(FilterKey, new ObservableCollection<CheckedListItem<string>>(CustomerFilters)); 

      RelationBetweenFiltersCheck(curFilter.Item.ToString()); 

      List<string> _filterValueList = new List<string>(); 
      foreach (var item in (FilterDictionary[curFilter.Key.ToString()] as ObservableCollection<CheckedListItem<string>>).Where(x => x.IsChecked == true)) 
      { 
       _filterValueList.Add(item.Item); 
      } 

      List<string> keyList = new List<string>(FilterDictionary.Keys); 

      SourceCollection = new ObservableCollection<dynamic>(); 

      foreach (var key in keyList) 
      { 
       foreach (var item in InputSourceCollection) 
       { 
        if (item.GetType().GetProperty(key) != null) 
        { 
         if (_filterValueList.Contains(item.GetType().GetProperty(key).GetValue(item, null).ToString())) 
         { 
          SourceCollection.Add(item); 
         } 
        } 
       } 
      } 

      OutputSource = SourceCollection; 

      RelationBetweenFiltersCheck(); 
     } 
    } 

    private void RelationBetweenFiltersCheck(string unCheckKey = null) 
    { 
     List<string> fileterKey = new List<string>(); 

     List<string> keyList = new List<string>(FilterDictionary.Keys); 

     foreach (var kItem in keyList) 
     { 
      if (fileterKey.Count == 0) 
      { 
       foreach (var item in OutputSourceCollection) 
       { 
        if (item.GetType().GetProperty(kItem) != null) 
         fileterKey.Add(item.GetType().GetProperty(kItem).GetValue(item, null).ToString()); 
       } 
      } 
      else if (fileterKey.Count > 0) 
      { 
       foreach (var item in OutputSourceCollection) 
       { 
        if (item.GetType().GetProperty(kItem) != null) 
         fileterKey.Add(item.GetType().GetProperty(kItem).GetValue(item, null).ToString()); 
       } 
      } 
     } 

     if (!string.IsNullOrEmpty(unCheckKey)) 
     { 
      if (fileterKey.Any(s => unCheckKey.Contains(s))) 
       fileterKey.Remove(unCheckKey); 
      else 
       fileterKey.Add(unCheckKey); 
     } 

     foreach (var item in FilterDictionary) 
     { 
      ObservableCollection<CheckedListItem<string>> cList = new ObservableCollection<CheckedListItem<string>>(); 
      cList = item.Value; 
      foreach (var sItem in cList) 
      { 
       sItem.IsChecked = fileterKey.Any(s => sItem.Item.Contains(s)); 
      } 
     } 
    } 


    private ObservableCollection<dynamic> IEnumeratorToObservableCollection(IEnumerable source) 
    { 

     ObservableCollection<dynamic> SourceCollection = new ObservableCollection<dynamic>(); 

     IEnumerator enumItem = source.GetEnumerator(); 
     var gType = source.GetType(); 
     string collectionFullName = gType.FullName; 
     Type[] genericTypes = gType.GetGenericArguments(); 
     string className = genericTypes[0].Name; 
     string classFullName = genericTypes[0].FullName; 
     string assName = (classFullName.Split('.'))[0]; 

     // Get the type contained in the name string 
     Type type = Type.GetType(classFullName, true); 

     // create an instance of that type 
     object instance = Activator.CreateInstance(type); 

     /// List of Propery for the above created instance of a dynamic class 
     List<PropertyInfo> oProperty = instance.GetType().GetProperties().ToList(); 

     while (enumItem.MoveNext()) 
     { 
      Object instanceInner = Activator.CreateInstance(type); 
      var x = enumItem.Current; 

      foreach (var item in oProperty) 
      { 
       if (x.GetType().GetProperty(item.Name) != null) 
       { 
        var propertyValue = x.GetType().GetProperty(item.Name).GetValue(x, null); 
        if (propertyValue != null) 
        { 
         // Get a property on the type that is stored in the 
         // property string 
         PropertyInfo prop = type.GetProperty(item.Name); 

         // Set the value of the given property on the given instance 
         prop.SetValue(instanceInner, propertyValue, null); 
        } 
       } 
      } 

      SourceCollection.Add(instanceInner); 
     } 

     return SourceCollection; 
    } 

} 

В XAML Код:

<cust:BListBox ItemsSource="{Binding CustomerFilters}" BorderThickness="0" FilterDictionary="{Binding dictionary, Mode= TwoWay, UpdateSourceTrigger=PropertyChanged}" FilterKey="{Binding FilterKey}" InputSource="{Binding MobileListPrimary}" OutputSource="{Binding MobileList, Mode=TwoWay}"> 
<cust:BListBox.ItemTemplate> 
    <DataTemplate> 
     <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item}" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterDataGrid}"> 
      <CheckBox.CommandParameter> 
       <MultiBinding Converter="{StaticResource DataGridConverterKey}"> 
        <Binding RelativeSource="{ RelativeSource 
              Mode=FindAncestor, 
              AncestorType={x:Type ListBox}}" /> 
        <Binding /> 
       </MultiBinding> 
      </CheckBox.CommandParameter> 
     </CheckBox> 
    </DataTemplate> 
</cust:BListBox.ItemTemplate> 

Как я могу установить значение для OutputSource в рамках метода

FilterResult(CheckedListItem<string> curFilter) 
{ 
///////////// 
// Refer the Above C# Code 

OutputSource = SourceCollection; 

// Refer the Above C# Code 
//////////// 
} 

Модель: -

public class MobileModel : Notify 
{ 
    private string _brand = string.Empty; 
    private ObservableCollection<MobileModelInfo> _model = new ObservableCollection<MobileModelInfo>(); 
    private string _os = string.Empty; 

    public string Brand 
    { 
     get { return _brand; } 
     set { _brand = value; OnPropertyChanged(); } 
    } 
    public ObservableCollection<MobileModelInfo> Model 
    { 
     get { return _model; } 
     set { _model = value; OnPropertyChanged(); } 
    } 

    public string OS 
    { 
     get { return _os; } 
     set { _os = value; OnPropertyChanged(); } 
    } 
} 

public class MobileModelInfo 
{ 
    public string Name { get; set; } 
    public string Catagory { get; set; } 
    public string Year { get; set; } 
} 

Загрузка модели в виде модели: -

public void GetMobile() 
    { 
     List<MobileModel> mList = new List<MobileModel>(); 
     List<MobileModelInfo> modList = new List<MobileModelInfo>(); 
     MobileModel mob = new MobileModel(); 

     modList.Clear(); 
     mob.Brand = "Apple"; 
     modList.Add(new MobileModelInfo { Name = "iPhone 4", Catagory = "Smart Phone", Year = "2011" }); 
     modList.Add(new MobileModelInfo { Name = "iPhone 5", Catagory = "Smart Phone", Year = "2013" }); 
     modList.Add(new MobileModelInfo { Name = "iPhone 6", Catagory = "Premium Smart Phone", Year = "2015" }); 
     mob.Model = new ObservableCollection<MobileModelInfo>(modList); 
     mob.OS = "IOS"; 
     mList.Add(mob); 

     mob = new MobileModel(); 
     modList.Clear(); 
     mob.Brand = "Samsung"; 
     modList.Add(new MobileModelInfo { Name = "S4", Catagory = "Smart Phone", Year = "2011" }); 
     modList.Add(new MobileModelInfo { Name = "S5", Catagory = "Smart Phone", Year = "2013" }); 
     modList.Add(new MobileModelInfo { Name = "S6", Catagory = "Ultra Smart Phone", Year = "2015" }); 
     mob.Model = new ObservableCollection<MobileModelInfo>(modList); 
     mob.OS = "Android"; 
     mList.Add(mob); 

     mob = new MobileModel(); 
     modList.Clear(); 
     mob.Brand = "MicroSoft"; 
     modList.Add(new MobileModelInfo { Name = "Lumina 9900", Catagory = "Phone", Year = "2011" }); 
     modList.Add(new MobileModelInfo { Name = "Opera X220", Catagory = "Smart Phone", Year = "2013" }); 
     mob.Model = new ObservableCollection<MobileModelInfo>(modList); 
     mob.OS = "Windows"; 
     mList.Add(mob); 

     mob = new MobileModel(); 
     modList.Clear(); 
     mob.Brand = "Sony Ericssion"; 
     modList.Add(new MobileModelInfo { Name = "S4", Catagory = "Smart Phone", Year = "2011" }); 
     modList.Add(new MobileModelInfo { Name = "S5", Catagory = "Smart Phone", Year = "2013" }); 
     modList.Add(new MobileModelInfo { Name = "S6", Catagory = "Ultra Smart Phone", Year = "2015" }); 
     mob.Model = new ObservableCollection<MobileModelInfo>(modList); 
     mob.OS = "Android"; 
     mList.Add(mob); 

     MobileListPrimary = new ObservableCollection<MobileModel>(mList); 
     MobileList = new ObservableCollection<MobileModel>(MobileListPrimary); 
    } 
+1

чем проблема с кодом вы сейчас имеете? –

+0

I Невозможно присвоить значение ** OutputSource ** с помощью кода OutputSource = SourceCollection; Он содержит только null, но SourceCollection имеет коллекцию. –

+0

Каков тип целевой привязки 'MobileList'? –

ответ

0

Вместо использования ObservableCollection<T> использования IEnumerable

зависимость Свойс у Декларация должна быть

public static readonly DependencyProperty OutputSourceCollectionProperty 
    = DependencyProperty.Register("OutputSourceCollection", 
     typeof(IEnumerable), 
     typeof(BListBox), 
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 

public IEnumerable OutputSourceCollection 
{ 
    get { return (IEnumerable)GetValue(OutputSourceCollectionProperty); } 
    set { SetValue(OutputSourceCollectionProperty, value); } 
} 

Использование IList Интерфейс Добавить/Удалить элементы

(OutputSourceCollection as IList).Add(Item); 

(OutputSourceCollection as IList).Remove(Item); 
1

Проблема заключается в том, что XAML привязки не смотря на фактический тип данных, но в данных тип свойства зависимостей, который равен IEnumerable. Переменная этого типа не может быть присвоена ObservableCollection<T>, и поэтому значение на вашей модели не обновляется.

Вы можете это исправить, добавив конвертер и использовать его в связывании:

public class EnumerableConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return null; 

     if (targetType.IsInstanceOfType(value)) 
      return value; 

     if (value.GetType().GetInterfaces().Contains(typeof(IEnumerable)) && targetType.IsGenericType 
      && !targetType.IsGenericTypeDefinition && targetType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) 
      return ((IEnumerable)value).Cast(targetType.GetGenericArguments().Single()); 

     throw new InvalidOperationException(
      string.Format("Can't convert from {0} to {1}", value.GetType(), targetType)); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return Convert(value, targetType, parameter, culture); 
    } 
} 

Этот код использует необщую версию Cast, так что вы будете нуждаться в этом классе, а также:

public static class EnumerableExtensions 
{ 
    private static readonly MethodInfo CastMethod; 

    static EnumerableExtensions() 
    { 
     CastMethod = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static); 
    } 

    public static object Cast(this IEnumerable input, Type targetType) 
    { 
     return CastMethod.MakeGenericMethod(targetType).Invoke(null, new object[] { input }); 
    } 
} 
+0

Я не могу получить ваш код ... Не могли бы вы реализовать свой класс с моим кодом ... –

+0

Это конвертер. используйте его в привязке в вашем файле XAML. –

+0

Я новичок в WPF. Итак, вы можете научить, как и где использовать этот конвертер в XAML? –

 Смежные вопросы

  • Нет связанных вопросов^_^