質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C#

    7453questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

【C#, WPF】ListBoxにIdの指すインスタンスをIdの代わりに表示したい

受付中

回答 2

投稿

  • 評価
  • クリップ 4
  • VIEW 1,506

NumAniCloud

score 40

質問の要点は以下のとおりです。
  • WPFでListBoxにID(int型)のリストをバインドしている。しかしListBoxにはIDそのものではなくIDの指すインスタンスの名前を表示したい。何かいい方法はないだろうか。
  • IDの指し示すデータはViewModelに用意されている。別の場所へ移しても構わない。

次のコードは、WPFでIDのリストにIDを追加していくことのできるアプリケーション コードの一部です。いま私が直面している問題を単純にしたものとなります。

class Hoge
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Hoge(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

class ViewModel
{
    // IDリスト
    public ObservableCollection<int> ObjectIds { get; set; }

    // IDの指すインスタンスのリスト
    public ObservableCollection<Hoge> AvailableHoges { get; set; }

    #region AddCommand

    private void AddCommandHandler(object parameter)
    {
        ObjectIds.Add((int)parameter);
    }

    public ICommand AddCommand
    {
        get
        {
            if(_AddCommand == null)
                _AddCommand = new DelegateCommand { CommandHandler = this.AddCommandHandler };
            return _AddCommand;
        }
    }
    private ICommand _AddCommand;

    #endregion

    public ViewModel()
    {
        AvailableHoges = new ObservableCollection<Hoge>()
        {
            new Hoge(1, "Foo"),
            new Hoge(2, "Bar"),
            new Hoge(3, "Fizz"),
        };
        ObjectIds = new ObservableCollection<int>();
    }
}

このViewModelを次のXAMLコードにバインディングしています。
<Window x:Class="IdBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <ListBox ItemsSource="{Binding ObjectIds}" Height="100"/>
        <ComboBox ItemsSource="{Binding AvailableHoges}"
            Name="combo"
            DisplayMemberPath="Name"
            SelectedValuePath="Id"/>
        <Button Content="追加"
            Command="{Binding AddCommand}"
            CommandParameter="{Binding SelectedValue, ElementName=combo}"/>
    </StackPanel>
</Window>

ComboBoxで選択しているHogeクラスのインスタンスのIdが、追加ボタンを押した時にListBoxにバインディングされているリストに追加される仕組みになっています。このままだとListBoxには追加されたIdの数字が表示されるのですが、今回はIdが指すAvailableHoge中のHogeクラスのNameを代わりに表示したいと思っています。期待する結果としては、この例ならリストに「1,1,2,3」と表示する代わりに「Foo,Foo,Bar,Fizz」と表示されるようにしたいと思っています。

この例ではListBoxにバインドされているObjectIdsをHogeクラスのリストに変更することでも解決するのですが、今直面している実際の問題ではObjectIdsの型を変更することが難しいため、別の方法を探しています。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

もっとも簡単で美しい解決策は「IDの型をenumに変更する」でしょうね。

enum ObjectID
{
    Foo = 1,
    Hoge = 2,
    Fizz = 3,
}
こうするだけで、とりあえず要件は満たせるはずです。(^<^)

もっとも現実はそれほど単純でなく、ローカライズなども考えると
IValueConverter インターフェイスを実装するクラスを作成する
または XAML で場合分けをきっちり書くことになりそうです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2014/12/06 19:21

    回答ありがとうございます。
    確かに今回の例はその方法で解決できるのですが、私の直面している実際の問題では以下の条件があるためこの方法が使えません。

    ・IDが指し示すオブジェクトは名前以外のメンバも持つ複雑なデータである。列挙型だと名前しか持つことができない。
    ・IDが指し示すオブジェクトはファイルから読み込むなどして動的に生成される。列挙型だと静的にしか変更できない。

    お見せした例に説明不足があったことをお詫びします。

    キャンセル

  • 2014/12/08 14:10

    まぁ…そうでしょうね。
    いきなりハシゴを外された感じが切ないです。

    AvailableHogesの内容は動的に生成されることからXAMLで解決するのは難しく、
    ObservableCollection=追加削除がランタイムで行われると考えると、ValueConverterによる実装も難しい。

    お役に立てず残念です。

    キャンセル

0

値コンバータを使ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

同じタグがついた質問を見る

  • C#

    7453questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。