开发者

Binding WPF ComboBox to List<MyClass> where MyClass doesn't have properties, just methods

开发者 https://www.devze.com 2023-01-17 02:25 出处:网络
I want to bind a combo box to a list of Device, List.I use, m_ctrlCB.DataContext = m_List; m_ctrlCB.DisplayMemberPath = \"ToString()\";

I want to bind a combo box to a list of Device, List. I use,

m_ctrlCB.DataContext = m_List;
m_ctrlCB.DisplayMemberPath = "ToString()";
m_ctrlCB.SelectedValuePath = "ToString()";  // do I even need this?

I don't have any properties in De开发者_JAVA百科vice to bind to and it's not my class. However, they do override ToString to something that is suitable for displaying in the combobox (something like: "Class Device. Number 1".

However, what I wrote doesn't work. What I see in the combobox is blank items. My selectionChanged event does work AND e.AddedItems[0] really is a Device, so I'm close. How can I get something meaningful to display in the combox box.

I suppose I'd also be happy creating ComboBoxItems and adding them to the ComboBox if necessary. But if I go this route, how do I set the Display stuff and the actual object itself so I can get it when the user selects it from the combobox?

Bonus question. If instead of using ToString, I want to use GetDeviceNumber() and combine it with my own test so the user sees, Device #1 Device #2 how would I do this?

thanks, Dave


You don't have to set the DisplayMemberPath and the SelectedValuePath. Since your Device object overrides ToString(), it should display the correct string on its own.

EDIT:

To answer your "bonus question", one way to do this is to use an IValueConverter that calls the method you're interested in. The sample code below demonstrates this. I have here a combobox whose items are represented by a TextBlock (which shows the value for the ToString() method), as well as a Button (which shows the value for the GetDeviceNumber() method).

XAML:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        Title="MainWindow" Height="350" Width="525"
        x:Name="window">
    <ComboBox x:Name="cb">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding}"/>
                    <Button>
                        <Button.Content>
                            <Binding>
                                <Binding.Converter>
                                    <local:DeviceValueConverter/>
                                </Binding.Converter>
                            </Binding>
                        </Button.Content>
                    </Button>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Window>

Code-Behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.cb.ItemsSource = new List<Device>()
        { 
            new Device("Device1"),
            new Device("Device2"),
            new Device("Device3"),
        };
    }
}

public class Device
{
    private string text;

    public Device(string text)
    {
        this.text = text;
    }

    public string GetDeviceNumber() { return this.GetHashCode().ToString(); }
    public override string ToString() { return this.text; }
}

public class DeviceValueConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Device)
        {
            return (value as Device).GetDeviceNumber();
        }
        return string.Empty;
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }

    #endregion
}


One way you could do it would be to create a wrapper class and provide the appropriate properties on it. For example:

class DeviceWrapper
{
    private Device device;

    public DeviceWrapper(Device device)
    {
        this.device = device;
    }

    public int DeviceNumber
    {
        return this.device.GetDeviceNumber();
    }

    // etc...
}


You should try to use ObjectDataProvider.

It will be something like this

...
  <UserControl.Resources>
    <ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="AlignmentValues">
      <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="HorizontalAlignment" />
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
  </UserControl.Resources>

  <Border Margin="10" BorderBrush="Aqua"
          BorderThickness="3" Padding="8">
    <StackPanel Width="300">
      <TextBlock>bla-bla</TextBlock>
      <ListBox Name="myComboBox" SelectedIndex="0" Margin="8"
               ItemsSource="{Binding Source={StaticResource AlignmentValues}}"/>
      <Button Content="Click Me!"
              HorizontalAlignment="{Binding ElementName=myComboBox,
                                            Path=SelectedItem}"/>
    </StackPanel>
  </Border>
...
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号