3

特定のタイプのアイテム、セッションを含むリストを実装しようとしています。各セッションには、タイプ Note を含むリストが含まれています。これらのメモを、それぞれのセッション ヘッダーの下のリストに表示したいと考えています。

現在、私は2つの異なる方法を試しました。最初の方法は、ItemsControlsasを使用することControlTemplateでしたListBoxItems。これは私が下の写真で使用したもので、リストをどのように表示したいかです。赤い四角形はそれぞれセッションを示し、ヘッダーの下の項目はメモです。問題は、個々のノートではなく、選択範囲からListBox選択することです。ItemsControls

GroupStyleリストを実装しようとしたもう 1 つの方法は、 で を使用するために、各 Note にそれが属するセッションのプロパティを与えることListBoxです。次に、ListBox の ItemsSource を Sessions ではなく Notes のリストに設定すると、図のように表示され、メモが選択されたリストが取得されます。ここでの問題は、メモを含まないセッションもリストに表示したいということです。

選択したリストを実装するために何を使用する必要があるかを知っている人はいますか?それは私が説明した方法で機能しますか?

4

2 に答える 2

3

MainWindow.xaml:

    <TreeView ItemsSource="{Binding}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:Session}" ItemsSource="{Binding Path=Notes}">
                <TextBlock Text="{Binding Path=Name}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:Note}">
                <Expander Header="{Binding Path=Notek}">
                    <TextBlock Foreground="Red" Text="{Binding Path=Details}" />
                </Expander>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        List<Session> sessions = new List<Session>();
        for (int i = 0; i < 5; i++)
        {
            List<Note> notes = new List<Note>();
            for (int j = i * 5; j < (i + 1) * 5; j++)
            {
                Note note = new Note()
                {
                    Notek = string.Format("Note {0}", j),
                    Details = string.Format("Note j = {0}{1}j*j = {2}", j, System.Environment.NewLine, j*j)
                };

                notes.Add(note);
            }
            Session session = new Session()
            {
                Name = string.Format("Session # {0}", i),
                Notes = notes
            };
            sessions.Add(session);
        }
        DataContext = sessions;
    }
}

public class Session
{
    public string Name { get; set; }
    public List<Note> Notes { get; set; }
}
public class Note
{
    public string Notek { get; set; }
    public string Details { get; set; }
}

好きなようにスタイリングできると思いますHierarchicalDataTemplate。例を示します。ItemsControlイベントハンドラーよりも簡単だと思います。

于 2012-08-07T07:36:08.567 に答える
1

回答を作成するために、次のデータ モデルを想定します。

class Session 
{
    public IEnumerable<Note> Notes { get; }
}

class Note { }

これには、リスト ボックスを同期するためのコーディングが必要です。「ListBoxGroup」という添付プロパティを作成しました。同じグループ名を持つすべてのリストボックスは、1 つの共有選択アイテムのみを持つことができます。コード量が多いので一番下に。

重要な注意事項:リストボックスの listboxgroup は、最初に設定した後に変更することはできず、アイテムの削除をサポートしていない、null などをチェックしていません。したがって、実行時にセッションを変更する必要がある場合は、グループからアイテムを削除する必要があります。 、リストボックスがビジュアル ツリーから削除されているかどうかなどを確認します。

まず、ページの XAML:

     xmlns:local="clr-namespace:YourApplication.YourNamespace"
    <!-- ItemsControl does not have selection -->
    <ItemsControl ItemsSource="{Binding SessionList}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <!-- Header for the session -->
                    <Border Background="Gray">
                        <TextBlock Text="{Binding Name}" />
                    </Border>
                    <!-- listbox for notes -->
                    <ListBox ItemsSource="{Binding Notes}" local:ListBoxGroup.GroupName="Group1">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <!-- Template for a single note -->
                                <TextBlock Text="{Binding Description}" />
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

以下は、ListBoxGroup プロパティの C# コードです。

public static class ListBoxGroup
{
    public static string GetGroupName(DependencyObject obj)
    {
        return (string)obj.GetValue(GroupNameProperty);
    }

    public static void SetGroupName(DependencyObject obj, string value)
    {
        obj.SetValue(GroupNameProperty, value);
    }

    // Using a DependencyProperty as the backing store for GroupName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty GroupNameProperty =
        DependencyProperty.RegisterAttached("GroupName", typeof(string), typeof(ListBoxGroup), new UIPropertyMetadata(null, ListBoxGroupChanged));

    private static Dictionary<string, List<ListBox>> _listBoxes = new Dictionary<string, List<ListBox>>();

    private static void ListBoxGroupChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        string newValue = e.NewValue as string;
        ListBox listBox = obj as ListBox;
        if (newValue == null || listBox == null) return;


        if (_listBoxes.ContainsKey(newValue))
        {
            _listBoxes[newValue].Add(listBox);
        }
        else
        {
            _listBoxes.Add(newValue, new List<ListBox>() { listBox });
        }

        listBox.SelectionChanged += new SelectionChangedEventHandler(listBox_SelectionChanged);
        listBox.PreviewKeyUp += new System.Windows.Input.KeyEventHandler(listBox_KeyUp);
    }

    static void listBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
    {
        ListBox listBox = sender as ListBox;

        if (e.Key == System.Windows.Input.Key.Up && listBox.SelectedIndex == 0)
        {
            //move to previous
            string groupName = GetGroupName(listBox);
            List<ListBox> group = _listBoxes[groupName];

            int senderIndex = group.IndexOf(listBox);
            if (senderIndex != 0)
            {
                listBox.SelectedItem = null;

                ListBox beforeSender = group[senderIndex - 1];

                int index = beforeSender.Items.Count - 1;
                beforeSender.SelectedIndex = index;

                var container = beforeSender.ItemContainerGenerator.ContainerFromIndex(index);

                (container as FrameworkElement).Focus();


            }
        }
        else if (e.Key == System.Windows.Input.Key.Down 
                    && listBox.SelectedIndex == listBox.Items.Count - 1)
        {
            //move to next
            string groupName = GetGroupName(listBox);
            List<ListBox> group = _listBoxes[groupName];

            int senderIndex = group.IndexOf(listBox);
            if (senderIndex != group.Count - 1)
            {
                listBox.SelectedItem = null;

                ListBox afterSender = group[senderIndex + 1];

                afterSender.SelectedIndex = 0;
                var container = afterSender.ItemContainerGenerator.ContainerFromIndex(0);

                (container as FrameworkElement).Focus();
            }
        }



    }

    static void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems.Count > 0)
        {
            ListBox listBox = sender as ListBox;
            string groupName = GetGroupName(listBox);

            foreach (var item in _listBoxes[groupName])
            {
                if (item != listBox)
                {
                    item.SelectedItem = null;
                }
            }

        }


    }
}
于 2012-08-07T07:18:26.953 に答える