如何在listView中绑定项目的子属性?

时间:2018-11-08 23:17:35

标签: c# .net wpf data-binding 2-way-object-databinding

我在尝试将一个属性绑定到另一个属性时陷入困境。 这两个属性是:

  • 在richTextBox中,“内容”依赖项属性
  • 在listView中,selectedItem是一本书,并且所选书具有一个名为“ End”的字符串属性。

我必须使用2个转换器将Content转换为字符串,并将字符串转换为Content,所以不能使用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->结束到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 :(得分:0)

更新后,我想我了解您要执行的操作。因此,我的理解是,您拥有一本书的清单,并且在选择一本书时,您只想更新自定义控件以反映出来。

如果没有通过代码绑定的特定原因,则可以使用以下技术。 (例如,我做了一个快速演示)

第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);
      }
 }
} 

如果您仍然在绑定时遇到问题,或者如果我误解了该问题,请告诉我。还提供您的自定义控件的代码。

答案 1 :(得分:0)

感谢您的回答,但是我只是找到了一个解决方案:实际上,我没有告诉您我尝试使用等于TwoWay的绑定模式,我告诉过您不可能。但是我错了,TwoWay与转换器兼容,因为转换器在每个转换方向上都包含两种方法。使用此代码是可能的:

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

,但格式丢失。我以为是由于缺少第二个转换器(在另一个方向)造成的,但是正如我刚才指出的那样,我错了。上面的代码不保留格式,因为它只是没有将其保存为纯文本!用HtmlToContentConverter替换转换器即可完成工作!

仍然感谢您度过的时间!