オフィスの元に戻すドロップダウン (下の画像) のようなものを達成する方法はありますか? つまり、ユーザーが最初以外の項目にマウスを置いたときに前の項目を強調表示したいですか? FluentRibbon からいくつかの制御を試みましたが、これまでのところ運がありません..
2 に答える
ほとんどの場合、このようなコントロールの設計は Blend で行われます。ただし、Blend の使用方法がわからない場合でも、XAML とコード ビハインドだけで同様の結果を得ることができますが、さらに多くの作業を行う必要があります。
CustomListBoxItem
から継承する というクラスを作成することから始めListBoxItem
ます。次に、リストボックス内のアイテムを強調表示するために使用される依存関係プロパティを定義します。
public class CustomListBoxItem : ListBoxItem
{
public static readonly DependencyProperty IsVirtuallySelectedProperty =
DependencyProperty.Register("IsVirtuallySelected", typeof(bool),
typeof(CustomListBoxItem),
new PropertyMetadata(false));
public CustomListBoxItem() : base()
{ }
public bool IsVirtuallySelected
{
get { return (bool)GetValue(IsVirtuallySelectedProperty); }
set { SetValue(IsVirtuallySelectedProperty, value); }
}
}
次に、リストボックスを追加し、XAML でスタイルを定義します。
<ListBox Name="listBox" MouseMove="listBox_MouseMove" SelectionChanged="listBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type local:CustomListBoxItem}">
<Style.Triggers>
<Trigger Property="IsVirtuallySelected" Value="true">
<Setter Property="Background" Value="SkyBlue"/>
</Trigger>
<Trigger Property="IsVirtuallySelected" Value="false">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
whereはが定義さlocal
れている名前空間です。CustomListBoxItem
XAML 部分に必要なのはこれだけです。本当の魔法はコード ビハインドで発生します。
イベント ハンドラは次のlistBox_MouseMove
ようになります。
private void listBox_MouseMove(object sender, MouseEventArgs e)
{
bool itemFound = false;
for (int i = 0; i < listBox.Items.Count; i++)
{
var currentItem = listBox.ItemContainerGenerator.ContainerFromIndex(i) as CustomListBoxItem;
if (currentItem == null)
continue;
// Check whether the cursor is on an item or not.
if (IsMouseOverItem(currentItem, e.GetPosition((IInputElement)currentItem)))
{
// Unselect all items before selecting the new group
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
// Select the current item and the ones above it
for (int j = 0; j <= listBox.Items.IndexOf(currentItem); j++)
{
((CustomListBoxItem)listBox.Items[j]).IsVirtuallySelected = true;
}
itemFound = true;
break;
}
}
// If the item wasn't found for the mouse point, it means the pointer is not over any item, so unselect all.
if (!itemFound)
{
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
}
}
また、IsMouseOverItem
カーソルがアイテム上にあるかどうかを判断するために使用されるヘルパー メソッドは、次のように定義されます。
private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
{
Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
return currentDescendantBounds.Contains(mouseOverPoint);
}
最後にlistBox_SelectedChanged
、ListBox のクリック ハンドラーとして機能するイベント ハンドラー:
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Get all the virtually selected items
List<CustomListBoxItem> selectedItems =
listBox.Items.Cast<CustomListBoxItem>().Where(x => x.IsVirtuallySelected).ToList();
if (selectedItems == null || !selectedItems.Any())
return;
// Do something with the selected items
DoCoolStuffWithSelectedItems();
// Unselsect all.
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
listBox.UnselectAll();
}
そしてブーム、私たちは終わりました。クラス コンストラクターの ListBox にいくつかの項目を追加できるようになりました。
public MainWindow()
{
InitializeComponent();
listBox.Items.Add(new CustomListBoxItem { Content = "hello world!" });
listBox.Items.Add(new CustomListBoxItem { Content = "wpf is cool" });
listBox.Items.Add(new CustomListBoxItem { Content = "today is tuesday..." });
listBox.Items.Add(new CustomListBoxItem { Content = "I like coffee" });
}
XAML で強調表示の色としてランダムな色を使用したことに注意してください。自由に変更して試してみてください。
次のようなものが必要だと思います:
<ControlTemplate TargetType="ListBoxItem">
<TextBlock Text="{Binding LastOperation}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger>
<DataTrigger.Binding>
<MultiBinding>
<Binding Path="MouseOverIndex"/>
<Binding Path="CurrentIndex"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Gold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>