【问题标题】:How to bind a WPF CustomControl to a ListBox如何将 WPF 自定义控件绑定到列表框
【发布时间】:2011-02-22 13:58:25
【问题描述】:

我正在尝试构建一个非常简单的联系人浏览器。我有一个显示在 ListBox 控件中的联系人对象集合,该控件显示联系人的全名,在右侧我有一个名为 BasicContactCard 的 customControl。这是显示 ListBox 的 ContacWindow 的 XAML:

<DockPanel Width="auto" Height="auto" Margin="8 8 8 8">
    <Border Height="56" HorizontalAlignment="Stretch" VerticalAlignment="Top" BorderThickness="1" CornerRadius="8" DockPanel.Dock="Top" Background="Beige">
        <TextBox Height="32" Margin="23,5,135,5" Text="Search for contact here" FontStyle="Italic" Foreground="#FFAD9595" FontSize="14" BorderBrush="LightGray"/>
    </Border>
    <ListBox x:Name="contactList" DockPanel.Dock="Left" Width="192" Height="auto" Margin="5 4 0 8" />
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="0.125*" />
        </Grid.RowDefinitions>
        <local:BasicContactCard Margin="8 8 8 8" />
        <Button Grid.Row="1" x:Name="exit" Content="Exit" HorizontalAlignment="Right" Width="50" Height="25" Click="exit_Click" />
    </Grid>
</DockPanel>

这是 CustomControl 的 XAML:

 <DockPanel Width="auto  " Height="auto" Margin="8,8,8,8">
    <Grid Width="auto" Height="auto" DockPanel.Dock="Top">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <TextBlock x:Name="companyField" Grid.Row="0" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="Company"/>
        <TextBlock x:Name="contactField" Grid.Row="1" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="Contact"/>
        <TextBlock x:Name="phoneField" Grid.Row="2" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="Phone"/>
        <TextBlock x:Name="emailField" Grid.Row="3" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="email"/>
    </Grid>
</DockPanel>

我遇到的问题是如何将 CustomControl 的各个元素绑定到 ListBox 中 SelectedItem 后面的对象?

【问题讨论】:

    标签: c# wpf-controls binding


    【解决方案1】:

    您可以将 ListBox 的 SelectedItem 属性用作用户控件的 DataContext(不是 DataSource,而是“类似”的东西)。

    假设你有这个对象:

    public class Contact
    {
        public string Name { get; set; }
        public string LastName { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
    

    然后这是你的新 XAML:

        <DockPanel Width="auto" Height="auto" Margin="8 8 8 8">
            <Border Height="56" HorizontalAlignment="Stretch" VerticalAlignment="Top" BorderThickness="1" CornerRadius="8" DockPanel.Dock="Top" Background="Beige">
                <TextBox Height="32" Margin="23,5,135,5" Text="Search for contact here" FontStyle="Italic" Foreground="#FFAD9595" FontSize="14" BorderBrush="LightGray"/>
            </Border>
            <ListBox x:Name="contactList" DockPanel.Dock="Left" Width="192" Height="auto" Margin="5 4 0 8" />
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="0.125*" />
                </Grid.RowDefinitions>
                <local:BasicContactCard Margin="8 8 8 8" />
                <Button Grid.Row="1" x:Name="exit" Content="Exit" HorizontalAlignment="Right" Width="50" Height="25" Click="exit_Click" />
            </Grid>
        </DockPanel>
    
        <DockPanel Width="auto  " Height="auto" Margin="8,8,8,8" DataContext="{Binding ElementName='contactList', Path=SelectedItem}">
            <Grid Width="auto" Height="auto" DockPanel.Dock="Top">
                <Grid.RowDefinitions>
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="1*" />
                </Grid.RowDefinitions>
                <TextBlock x:Name="companyField" Grid.Row="0" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="{Binding Company }"/>
                <TextBlock x:Name="contactField" Grid.Row="1" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="{Binding Contact }"/>
                <TextBlock x:Name="phoneField" Grid.Row="2" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="{Binding Phone }"/>
                <TextBlock x:Name="emailField" Grid.Row="3" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="8,8,8,8" Text="{Binding Email }"/>
            </Grid>
        </DockPanel>
    

    关键部分是这样的:

        <DockPanel Width="auto  " Height="auto" Margin="8,8,8,8" DataContext="{Binding ElementName='contactList', Path=SelectedItem}">
    

    当然,看看如何获​​取TextBlock的值:

    Text="{绑定公司}"/>

    您正在从“contactList”列表框的选定项设置 DockPanel 的 DataContext。

    我没有对其进行测试,但我认为您对这两件事的关系有所了解。 祝你好运。

    【讨论】:

      【解决方案2】:

      我认为将DataTemplate 用于ItemTemplatesListBox 是更好的选择。无需使用 CustomControl。 DataTemplate 定义列表中每个项目的外观。

      【讨论】:

      • 感谢 DHN 的指点。我一直想知道我是否让它变得比需要的更复杂,但是由于到目前为止,与 WinForms 相比,WPF 的一切对我来说都是一场艰苦的斗争,我认为这是前进的道路!我现在就去看看 DataTemplates。但是,如果我们确实使用自定义控件,如何将 textblock.text 属性绑定到 ListBox.SelectedItem?现在这更多是出于想要学习的目的,或者这只是我所做的一个设计糟糕的学习项目,而现实世界的实现不会出现在这种情况下?
      • 我还没做过,但我猜CustomControl定义了一个DependencyProperty,比如'ItemSource'或'DataContext',所以可以从调用者绑定数据。因此,如何解释数据取决于控制。
      【解决方案3】:

      嗯,我最终想通了,它比我想象的要简单得多!呵呵!

      基本上,我将 ContactWindow 中 Grid 对象的 DataContext 设置为 ListBox,这样 Grid 内的任何对象都将继承 DataContext。

      <DockPanel Width="auto" Height="auto" Margin="8 8 8 8">
          <Border Height="56" HorizontalAlignment="Stretch" VerticalAlignment="Top" BorderThickness="1" CornerRadius="8" DockPanel.Dock="Top" Background="Beige">
              <TextBox Height="32" Margin="23,5,135,5" Text="Search for contact here" FontStyle="Italic" Foreground="#FFAD9595" FontSize="14" BorderBrush="LightGray"/>
          </Border>
          <ListBox x:Name="contactList" DockPanel.Dock="Left" Width="192" Height="auto" Margin="5 4 0 8" ItemsSource="{Binding}" DisplayMemberPath="FullName" />
          <Grid DataContext="{Binding ElementName=contactList, Path=SelectedItem}">
              <Grid.RowDefinitions>
                  <RowDefinition Height="1*" />
                  <RowDefinition Height="0.125*" />
              </Grid.RowDefinitions>
              <local:BasicContactCard Margin="8 8 8 8" />
              <Button Grid.Row="1" x:Name="exit" Content="Exit" HorizontalAlignment="Right" Width="50" Height="25" Click="exit_Click" />
          </Grid>
      </DockPanel>
      

      希望这可以帮助与我在同一条船上学习的其他人。

      【讨论】:

      • 我要感谢 Markust,因为他最初为我指出了正确的方向,但它花了很长时间才进入我相当困惑的大脑!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      相关资源
      最近更新 更多