タイトルは私がやろうとしていることを示しています。ここに私が持っているものがあります:
このCodeProject の貢献を使用して、RubberBand 動作を ListBox にアタッチし、マウスを使用してドラッグ選択できるようにしています。ListBox を非インタラクティブにしてアイテムのみを表示する必要がある場合に備えて、ListBox のインスタンス化中に無効にできるように、それを変更することができました。
ListBox は UserControl に埋め込まれ、要素を表示するキャンバスが含まれています。プログラムのあるセクションでは、UserControl をそれらの要素の非インタラクティブな表現にする必要がありましたが、他のセクションではインタラクティブにする必要がありました。しかし、現在、これら 2 つの状態を切り替える必要がありますが、残念ながら、ATM を使用している実装では機能せず、その理由がわかりません。
修正したラバーバンド バージョン (以下のコードを参照) に追加した添付プロパティ 'IsActive' を、UserControl-ViewModel のプロパティ 'IsEditable' にバインドしましたが、何らかの理由でメソッド 'IsActiveProperty_Changed' が実行されません。 「IsEditable」の変更。
これは、動作を使用して「IsEditable」にバインドしています。
<i:Interaction.Behaviors>
<behavior:RubberBandBehavior IsActive="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.IsEditable}"/>
</i:Interaction.Behaviors>
私もこれを試しましたが、これも機能しません:
<behavior:RubberBandBehavior IsActive="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.IsEditable, UpdateSourceTrigger=PropertyChanged}"/>
ListBox のヒット検出を無効にするために、「IsEditable」にもバインドしています。これは正常に機能します。
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.IsEditable}" Value="False">
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Focusable" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
したがって、添付プロパティの実装にまだ慣れていないため、RubberBandBehavior の実装/変更に関係していると思われます。誰かが私のエラーを見つけてくれることを願っています。
変更された RubberBandBehavior.cs
public class RubberBandBehavior : Behavior<ListBox>
{
private RubberBandAdorner band;
private AdornerLayer adornerLayer;
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register("IsActive", typeof(bool), typeof(RubberBandBehavior),
new PropertyMetadata(IsActiveProperty_Changed));
private static void IsActiveProperty_Changed(DependencyObject sender,
DependencyPropertyChangedEventArgs args)
{
RubberBandBehavior rubberBandBehavior = (RubberBandBehavior)sender;
if (args.Property.Name == "IsActive")
{
bool newIsActiveValue = (bool)args.NewValue;
bool oldIsActiveValue = (bool)args.OldValue;
if (newIsActiveValue != oldIsActiveValue)
{
rubberBandBehavior.IsActive = newIsActiveValue;
if (rubberBandBehavior.AssociatedObject != null)
{
if (newIsActiveValue == true)
{
rubberBandBehavior.AttachBehavior();
}
else
{
rubberBandBehavior.DetachBehavior();
}
}
}
}
}
public bool IsActive
{
get { return (bool)GetValue(IsActiveProperty); }
set { SetValue(IsActiveProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.Loaded += new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
base.OnAttached();
}
void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
if (IsActive == true)
{
AttachBehavior();
}
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
base.OnDetaching();
}
private void AttachBehavior()
{
band = new RubberBandAdorner(AssociatedObject);
adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject);
adornerLayer.Add(band);
}
private void DetachBehavior()
{
adornerLayer.Remove(band);
}
}
RubberBandAdorner.cs:
public class RubberBandAdorner : Adorner
{
private Point startpoint;
private Point currentpoint;
private Brush brush;
private bool flag;
private ScrollViewer viewer;
private ScrollBar scrollbar;
public RubberBandAdorner(UIElement adornedElement)
:base(adornedElement)
{
IsHitTestVisible = false;
adornedElement.MouseMove += new MouseEventHandler(adornedElement_PreviewMouseMove);
adornedElement.MouseLeftButtonDown += new MouseButtonEventHandler(adornedElement_PreviewMouseLeftButtonDown);
adornedElement.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(adornedElement_PreviewMouseLeftButtonUp);
brush = new SolidColorBrush(SystemColors.HighlightColor);
brush.Opacity = 0.3;
}
void adornedElement_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DisposeRubberBand();
}
void adornedElement_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListBox _selector = AdornedElement as ListBox;
if (_selector.SelectedItems != null && (_selector.SelectionMode == SelectionMode.Extended || _selector.SelectionMode == SelectionMode.Multiple))
{
_selector.SelectedItems.Clear();
}
startpoint = Mouse.GetPosition(this.AdornedElement);
Mouse.Capture(_selector);
flag = true;
}
public static childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
// Search immediate children first (breadth-first)
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
void adornedElement_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && flag)
{
currentpoint = Mouse.GetPosition(AdornedElement);
Selector _selector = AdornedElement as Selector;
if (viewer == null)
{
viewer = FindVisualChild<ScrollViewer>(_selector);
}
if (scrollbar == null)
{
scrollbar = FindVisualChild<ScrollBar>(viewer);
}
if (_selector.Items.Count > 0)
{
if (currentpoint.Y > ((FrameworkElement)AdornedElement).ActualHeight && viewer.VerticalOffset < _selector.ActualHeight && scrollbar.Visibility == System.Windows.Visibility.Visible)
{
startpoint.Y -= 50;
}
else if (currentpoint.Y < 0 && viewer.VerticalOffset > 0 && scrollbar.Visibility == System.Windows.Visibility.Visible)
{
startpoint.Y += 50;
}
}
InvalidateVisual();
foreach (var obj in _selector.Items)
{
ListBoxItem item = _selector.ItemContainerGenerator.ContainerFromItem(obj) as ListBoxItem;
if (item != null)
{
Point point = item.TransformToAncestor(AdornedElement).Transform(new Point(0, 0));
Rect bandrect = new Rect(startpoint, currentpoint);
Rect elementrect = new Rect(point.X, point.Y, item.ActualWidth, item.ActualHeight);
if (bandrect.IntersectsWith(elementrect))
{
item.IsSelected = true;
}
else
{
item.IsSelected = false;
}
}
}
}
}
protected override void OnRender(DrawingContext drawingContext)
{
Rect rect = new Rect(startpoint, currentpoint);
drawingContext.DrawGeometry(brush, new Pen(SystemColors.HighlightBrush, 1), new RectangleGeometry(rect));
base.OnRender(drawingContext);
}
private void DisposeRubberBand()
{
currentpoint = new Point(0, 0);
startpoint = new Point(0, 0);
AdornedElement.ReleaseMouseCapture();
InvalidateVisual();
flag = false;
}
}
アップデート:
IsEditable
ViewModelのプロパティのコードは次のとおりです。RaisePropertyChanged
MvvmLightのメソッドを使用していることに注意してください。
private bool isEditable;
public bool IsEditable
{
get { return isEditable; }
set {
if(value != isEditable)
{
isEditable = value;
RaisePropertyChanged("IsEditable");
}
}
}