在RibbonSplitButton中突出显示上面的所有元素

时间:2018-08-01 15:04:11

标签: c# wpf

我试图复制Visual Studio(可能还有其他)功能,以突出显示列表中鼠标所在项目上方出现的所有元素。

VisualStudioImage

(请注意,鼠标位于顶部的第6行上方)。如图所示,当鼠标悬停在第6个元素上时,撤消命令1-5将突出显示。

目前,我正在尝试在实际程序中实现虚拟应用程序之前先对其做些什么。我找到了this解决方案,但它使用了一个列表框,并且与动态添加项目时的添加方法不兼容。这是我到目前为止的内容:

在我的XAML中:

<TextBox Width="60" Margin="2" Text="{Binding SomeText, UpdateSourceTrigger=PropertyChanged}"/>
<RibbonSplitButton Label="Add" HorizontalContentAlignment="Center" Command="{Binding addToStack}" ItemsSource="{Binding Path=AddedItems}" VerticalContentAlignment="Center" Margin="2" Padding="2" Name="AddRSB" MouseOverBackground="{x:Static SystemColors.HighlightBrush}" MouseMove="RibbonSplitButton_MouseMove">
    <RibbonSplitButton.Resources>
        <Style TargetType="{x:Type RibbonMenuItem}">
            <Style.Triggers>
                 <DataTrigger Binding="{Binding Path=SelectedBelow}" Value="True">
                      <Setter Property="MouseOverBorderBrush">
                          <Setter.Value>
                              <SolidColorBrush Color="Red" Opacity="0.5"/>
                          </Setter.Value>
                      </Setter>
                      <Setter Property="MouseOverBackground">
                          <Setter.Value>
                              <SolidColorBrush Color="Red" Opacity="0.1"/>
                          </Setter.Value>
                       </Setter>
                       <Setter Property="BorderBrush">
                           <Setter.Value>
                               <SolidColorBrush Color="Red" Opacity="0.5"/>
                           </Setter.Value>
                       </Setter>
                       <Setter Property="Background">
                           <Setter.Value>
                               <SolidColorBrush Color="Red" Opacity="0.1"/>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            <Setter Property="Foreground" Value="Red"/>
        </Style>
    </RibbonSplitButton.Resources>
</RibbonSplitButton>

在我的ViewModel中:

private ObservableCollection<CustomRibbonMenuItem> _add = new ObservableCollection<CustomRibbonMenuItem>();
public IEnumerable<CustomRibbonMenuItem> AddedItems
{
    get
    {
        return _add;
    }
}
private string _sometext;
public string SomeText
{
    get
    {
        return _sometext;
    }
    set
    {
        _sometext = value;
        RaisePropertyChanged(nameof(SomeText));
    }
}
public DelegateCommand<object> addToStack => new DelegateCommand<object>((o) => AddNum(o));
public void AddNum(object o)
{
    int.TryParse(SomeText, out int num);
    var crmi = new CustomRibbonMenuItem(num);
    _add.Insert(0, crmi);
    SomeText = string.Empty;
    RaisePropertyChanged(nameof(AddedItems));
    RaisePropertyChanged(nameof(AddHasContent));
    RaisePropertyChanged(nameof(RemoveHasContent));
}

({DelegateCommand使用ICommandRaisePropertyChanged使用INotifyPropertyChanged)。我的CustomRibbonMenuItem课:

private bool _selectedBelow = false;
public int Number { get; set; }
public bool SelectedBelow
{
    get { return _selectedBelow; }
    set
    {
        if (value == _selectedBelow)
            return;

        _selectedBelow = value;
        RaisePropertyChanged(nameof(SelectedBelow));
    }
}

public CustomRibbonMenuItem(int number)
{
    Number = number;
    SelectedBelow = false;
}

public override string ToString()
{
    return Number.ToString();
}

最后,在我后面的代码中:

private void RibbonSplitButton_MouseMove(object sender, MouseEventArgs e)
{
    var itemSelected = false;
    for(int i = AddRSB.Items.Count - 1; i >= 0; i--)
    {
        var currentItem = AddRSB.ItemContainerGenerator.ContainerFromIndex(i) as RibbonMenuItem;
        if(currentItem != null)
        {
            if (itemSelected)
            {
                ((CustomRibbonMenuItem)currentItem.DataContext).SelectedBelow = true;
            }
            else if(IsMouseOverItem(currentItem, e.GetPosition(currentItem)))
            {
                ((CustomRibbonMenuItem)currentItem.DataContext).SelectedBelow = true;
                itemSelected = true;
            }
            else
            {
                ((CustomRibbonMenuItem)currentItem.DataContext).SelectedBelow = false;
            }
        }
    }
}

问题是鼠标悬停的项目上方的项目在左侧具有淡入淡出的效果。

WeirdFading

如果删除MouseOver...属性,则所有突出显示的部分似乎都在突出显示和未突出显示之间闪烁。如何摆脱褪色的部分?是否有更好的方法来实现此功能({RibbonSplitButtonMouseMoveEvent似乎是我要完成的工作的最佳选择)?

1 个答案:

答案 0 :(得分:1)

只需在RibbonMenuItem样式中设置Template属性,就不会再获得渐变效果:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate>
            <Border Width="auto"
                    MinWidth="50"
                    CornerRadius="3"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    BorderBrush="{TemplateBinding BorderBrush}">
                <TextBlock Text="{Binding}"
                           Padding="15,3"
                           HorizontalAlignment="Stretch"
                           TextAlignment="Left"
                           Background="{TemplateBinding Background}"
                           Foreground="{TemplateBinding Foreground}" />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>