Как связать подчиненное свойство элемента в listView? - PullRequest
0 голосов
/ 09 ноября 2018

Я застрял при попытке привязать свойство к другому свойству. 2 свойства:

  • в richTextBox, свойство зависимости 'Content'
  • в listView выбранный элемент представляет собой книгу, а выбранная книга имеет строковое свойство с именем «Конец».

Мне нужно использовать 2 конвертера для преобразования Контента в строку, а строки в Контент, поэтому я не могу использовать режим привязки TwoWay.

С этим кодом:

<controls:RichEditControl
    x:Name="richEditControl1"
    BarManager="{Binding ElementName=barManager1, Mode=OneTime}"
    HorizontalRulerVisibility="Collapsed"
    VerticalRulerVisibility="Collapsed"
    Content="{Binding ElementName=listBoxBooks, Path=SelectedItem.End, Converter={StaticResource PlainContentConverter}, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>

должна быть половина привязки, но я не могу понять, как реализовать вторую половину, я имею в виду listView -> (Book) selectedItem -> End to свойство Content.

Я пробовал что-то вроде этого:

Binding myBinding = new Binding("Content");
myBinding.Source = richEditControl1;
myBinding.Mode = BindingMode.OneWay;
listBoxBooks.SetBinding(ListView.SelectedItemProperty, myBinding);

но это неправильно, поскольку я не хочу связывать весь SelectedItemProperty, а только его свойство 'End'. (selectedItem является классом 'Book').

спасибо.

EDIT1 Я изменил код, следуя совету, данному в комментарии, но безуспешно код:

Binding myBinding = new Binding("End");
myBinding.Source = (Book)listBoxBooks.SelectedItem;
myBinding.Mode = BindingMode.OneWay;
richEditControl1.SetBinding(RichEditControl.ContentProperty, myBinding);

(фактически это инвертирует направление привязки, но я думаю, что первое направление было неправильным).

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

спасибо за ваш ответ, но я только что нашел решение: на самом деле, я не сказал вам, что я пробовал с режимом привязки, равным TwoWay, я сказал вам, что это невозможно. Но я был неправ, TwoWay совместим с конвертером, так как конвертер содержит два метода для каждого направления конвертации. Это было возможно, с этим кодом:

Content="{Binding ElementName=listBoxBooks, Path=SelectedItem.End,Converter={StaticResource PlainToContentConverter},UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>

но форматирование потеряно. Я думал, что это было вызвано отсутствием второго преобразователя (в другом направлении), но, как я только что указал, я был неправ. Приведенный выше код не сохраняет форматирование, потому что он просто не сохраняет его в виде обычного текста! Замена конвертера HtmlToContentConverter делает свою работу!

В любом случае, спасибо за потраченное время!

0 голосов
/ 09 ноября 2018

После обновления я думаю, что понимаю, что вы пытаетесь сделать. Насколько я понимаю, у вас есть список книг, и при выборе книги вы просто хотите обновить свой пользовательский элемент управления, чтобы отразить его.

Если нет конкретной причины для привязки с помощью кода, вы можете использовать следующую технику. (Например, я сделал короткую демонстрацию на моем конце)

Шаг 1. Настройте XAML для привязки непосредственно к Listbox.SelectedItem.

<Window x:Class="TestWPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestWPF"
    mc:Ignorable="d"
    Title="MainWindow" Height="600" Width="800">

<Window.Resources>
    <local:DummyConverter x:Key="DummyConverter"/>
</Window.Resources>


<Grid Margin="15">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListBox x:Name="MyListOfBooks" ItemsSource="{Binding Path=BookCollection, Mode=OneWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Title, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                    <TextBlock Text="{Binding Path=End, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat='dddd, dd MMMM yyyy'}" Margin="30,0,0,0"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <!--Replace with custom control, make sure your custom control has a dependancy property for this binding-->
    <TextBox x:Name="MyTextBox" Grid.Column="2" Text="{Binding Path=SelectedItem.Title, ElementName=MyListOfBooks, Converter={StaticResource DummyConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>

</Grid>
</Window>

Шаг 2: Вот мой демонстрационный код, чтобы помочь.

namespace TestWPF
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
      MainViewModel model;
      public MainWindow()
      {
          InitializeComponent();
          this.Loaded += MainWindow_Loaded;
      }

      private void MainWindow_Loaded(object sender, RoutedEventArgs e)
      {
          model = new MainViewModel();
          model.Load();
          this.DataContext = model;
      }       
  }

  public class MainViewModel
  {
      public ObservableCollection<Book> BookCollection { get; set; }

      public void Load()
      {
          BookCollection = new ObservableCollection<Book>
          {
              new Book() { Title = "Book One", End = DateTime.Now },
              new Book() { Title = "Book Two", End = DateTime.Now.AddDays(10) },
              new Book() { Title = "Book Three", End = DateTime.Now.AddDays(2) }
          };
      }
  }

  public class Book : INotifyPropertyChanged
  {
     private string title;
     private DateTime end;

     public string Title
     {
        get { return title; }
        set
        {
            title = value;
            NotifyPropertyChanged();
        }
     }
     public DateTime End
     {
         get { return end; }
         set
         {
            end = value;
            NotifyPropertyChanged();
         }
      }

      public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
      {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }

      public event PropertyChangedEventHandler PropertyChanged;
   }


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

        System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
        return string.Join("-", encoding.GetBytes((value as string) ?? string.Empty));
      }


      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {
          if (value == null)
              return null;

          string val = (value as string);

          var array = val.Split('-');
          Byte[] byteArray = new Byte[array.Length];
          for (int i = 0; i < array.Length; i++)
          {
              Byte.TryParse(array[i], out byte x);
            byteArray[i] = x;
          }

          return Encoding.ASCII.GetString(byteArray);
      }
 }
} 

Если у вас все еще есть проблемы с переплетом или если я неправильно понял проблему, пожалуйста, дайте мне знать. Также предоставьте код для вашего пользовательского контроля.

...