Using .NET 4 and VS2010 Pro, I've created a very simple WPF Application that contains the following XAML in the MainWindow:
<Grid>
<RichTextBox x:Name="richTextBox"
Margin="2"/>
</Grid>
All I would like to do, and have so far been unsuccessful at doing, is to replace the ContextMenu for the RichTextBox with my own. I've tried the code-behind from MSDN with no luck:
public MainWindow()
{
InitializeComponent();
richTextBox.ContextMenuOpening += new ContextMenuEventHandler(richTextBox_ContextMenuOpening);
}
private void richTextBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
RichTextBox rtb = sender as RichTextBox;
if (rtb == null)
{
return;
}
ContextMenu contextMenu = rtb.ContextMenu;
contextMenu.Items.Clear();
MenuItem menuItem = new MenuItem();
menuItem.Header = "Test";
contextMenu.Items.Add(menuItem);
contextMenu.PlacementTarget = rtb;
contextMenu.Placement = PlacementMode.RelativePoint;
TextPointer position = rtb.Selection.End;
if (position == null)
{
return;
}
Rect positionRect = position.GetCharacterRect(LogicalDirection.Forward);
contextMenu.HorizontalOffset = positionRect.X;
contextMenu.VerticalOffset = positionRect.Y;
contextMenu.IsOpen = true;
e.Handled = true;
}
I'm at a loss for what I'm not doing correctly. Does it have to with the MouseDown event being caught by the RTB? Do I have to derive my own version of the RTB and override ContextMenuOpening to get this to work? This seems like something really simple but I'm just not seeing it.
Thanks in advance.
Set the ContextMenu property on your RichTextBox to something other than null:
<RichTextBox x:Name="richTextBox"
Margin="2">
<RichTextBox.ContextMenu>
<ContextMenu/>
</RichTextBox.ContextMenu>
</RichTextBox>
TextBoxBase, the base class of RichTextBox, has logic to automatically supply a context menu with things like Copy and Paste. This logic marks the ContextMenuOpening as handled, so your handler is not invoked. If you assign even an empty ContextMenu to your RichTextBox, it will leave your ContextMenu alone and invoke your handler.
Related
I have a common task. Implement CheckBox checking in DataGrid by one-click. I deside make a DataGridExtended class, derived from DataGrid, and implement something like that:
XAML:
<DataGrid x:Class="DataGrid.DataGridExtended"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
</DataGrid>
CODE:
public partial class DataGridExtended : System.Windows.Controls.DataGrid
{
private int _oldRowIndex;
private int _oldColumnIndex;
public DataGridExtended()
{
MouseLeftButtonUp += DataGridExtendedMouseLeftButtonUp;
MouseLeftButtonDown += DataGridExtendedMouseLeftButtonDown;
}
private void DataGridExtendedMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Если сендер реально DataGridExtended
var dataGridExt = sender as DataGridExtended;
if (dataGridExt == null)
return;
// Получаем текущую ячейку
var currentCell = dataGridExt.CurrentCell;
_oldRowIndex = dataGridExt.SelectedIndex;
_oldColumnIndex = dataGridExt.CurrentColumn.DisplayIndex;
}
private void DataGridExtendedMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
// Если сендер реально DataGridExtended
var dataGridExt = sender as DataGridExtended;
if (dataGridExt == null)
return;
var rowIndex = dataGridExt.SelectedIndex;
var columnIndex = dataGridExt.CurrentColumn.DisplayIndex;
// Получаем текущую ячейку
var currentCell = dataGridExt.CurrentCell;
//if (_oldRowIndex != rowIndex || _oldColumnIndex != columnIndex)
// return;
// Получаем текущую колонку
var currentColumn = currentCell.Column;
// Получаем контент текущей ячейки
var cellContent = currentColumn.GetCellContent(currentCell.Item);
// Если кликнули по чекбоксу
var checkBox = cellContent as CheckBox;
if (checkBox == null)
return;
// Ставием его в фокус
checkBox.Focus();
// Меняем чек на противоположный
checkBox.IsChecked = !checkBox.IsChecked;
// Получаем выражение привязки для чекбокса
var bindingExpression = checkBox.GetBindingExpression(ToggleButton.IsCheckedProperty);
// Если привязка есть - обновляем ее
if (bindingExpression != null)
bindingExpression.UpdateSource();
}
}
DataGridExtendedMouseLeftButtonUp handler works fine, but DataGridExtendedMouseLeftButtonDown doesn't firing. And that is the problem.
Without DataGridExtendedMouseLeftButtonDown invoking, checking behaviour is not what I want. Namely, checking is working even I move cursor out from grid :E
Trying to use PreviewMouseLeftButtonDown instead MouseLeftButtonDown give wrong effect :(
So, how can I solve my problem? Don't offer use different approaches to implement one-click checking plz :) Like using XAML-style for example...
In WPF, we often get situations where a particular Click handler appears not to work. The reason for this is usually because a control (or our own code) is handling that event and setting e.Handled = true;, which stops the event from being passed any further. In these situations, it is generally accepted that you should try to access the event before this happens and so we turn to the matching/related Preview event.
In your situation, I would recommend that you use the PreviewMouseLeftButtonDown event. You said that something is not initialized by then, but that doesn't make any sense to me. You said that you need to save the previous value, but you could do that just from your DataGridExtendedMouseLeftButtonUp event handler.
When the user releases the mouse button the first time, then you have their new value. Save this in a variable. When the user releases the mouse button the next and each subsequent time, then save their previous value from the variable as the old value and then read their new value into the variable.
Try MouseDown event and then figure out right or left
I've found some info on StackOverflow regarding my problem, so I introduced the following XAML code to my window.
Now everything is fine, while the WPF window hasn't quick launch icons or contextual tabs active.
Is there a way to center the application title completely via XAML Code.
<ribbon:Ribbon.TitleTemplate>
<DataTemplate>
<TextBlock TextAlignment="Center" HorizontalAlignment="Stretch"
Width="{Binding ElementName=Window, Path=ActualWidth}">ApplicationTitle
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="0" Color="MintCream " BlurRadius="10"/>
</TextBlock.Effect>
</TextBlock>
</DataTemplate>
</ribbon:Ribbon.TitleTemplate>
Here's a very naïve way to do it. It comes about from inspecting the visual tree of a RibbonWindow and its concomitant Ribbon. I've been playing with this code for a couple of hours (and no longer) -- it's a bit rough around the edges and I'm not sure it's completely bug free. There's some optimizations to be made and it should be noted that I suck at WPF; there might be better way to do things.
For what it's worth the code is below, but note first:
The references to the PART_Icon template are not directly related to your question, but it is related to the aesthetics of the window.
The references to IsWin8OrHigher and FindChild are in classes that I'll include at the end. My interest in Windows 8 is that the native ribbon library centres the title text, whereas earlier versions of Windows do not. I'm trying to emulate that here.
I have no idea how the RibbonWindow was shipped with Visual Studio 2012 in its current iteration. The rendering on Windows 8 looks pretty miserable. After all this, I'm tempted to overload TitleTemplate with a TextBlock to get rid of the default glow and leave it at that.
The RibbonWindow doesn't look very good maximized, customization or not.
When I started writing this code, this was approximately what I was aiming for:
For comparison, this is how the RibbonWindow renders itself with no customisation:
This is how it renders with TitleTemplate defined to a TextBlock with TextAlignment="Center" but otherwise without any fancy text effects:
With the code below, we get this result:
MainWindow:
public partial class MainWindow {
public MainWindow() {
InitializeComponent();
if (Environment.OSVersion.IsWin8OrHigher()) {
SizeChanged += (sender, args) => TitleHack();
Activated += (sender, args) => TitleHack();
}
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
if (!Environment.OSVersion.IsWin8OrHigher())
return;
var icon = GetTemplateChild("PART_Icon") as Image;
if (icon == null)
return;
icon.Margin = new Thickness(icon.Margin.Left + 3, icon.Margin.Top + 2,
icon.Margin.Right, icon.Margin.Bottom);
}
private void TitleHack() {
var ribbonTitlePanel = MyRibbon.FindChild<FrameworkElement>("PART_TitlePanel");
var qatTopHost = MyRibbon.FindChild<FrameworkElement>("QatTopHost");
var titleHost = MyRibbon.FindChild<FrameworkElement>("PART_TitleHost");
var tabGroup = MyRibbon.FindChild<FrameworkElement>("PART_ContextualTabGroupItemsControl");
var qatTopHostLeft = qatTopHost.TransformToAncestor(ribbonTitlePanel).Transform(new Point(0, 0)).X;
var tabGroupLeft = tabGroup.TransformToAncestor(ribbonTitlePanel).Transform(new Point(0, 0)).X;
var width = ribbonTitlePanel.ActualWidth;
if (tabGroup.Visibility == Visibility.Visible) {
width -= tabGroup.ActualWidth;
width -= tabGroupLeft - qatTopHostLeft;
} else {
width -= qatTopHost.ActualWidth;
}
if (ResizeMode != ResizeMode.NoResize && WindowStyle != WindowStyle.None)
width -= 48; // For the min and max buttons
titleHost.Width = width > 0 ? width : Double.NaN;
}
}
OperatingSystemExtensionMethods.cs:
public static class OperatingSystemExtensionMethods {
private static readonly Version Windows8Version = new Version(6, 2);
public static bool IsWin8OrHigher(this OperatingSystem that) {
if (that.Platform != PlatformID.Win32NT)
return false;
return that.Version.CompareTo(Windows8Version) >= 0;
}
}
DependencyObjectExtensionMethods.cs:
public static class DependencyObjectExtensionMethods {
public static T FindChild<T>(this DependencyObject that, string elementName)
where T : FrameworkElement {
var childrenCount = VisualTreeHelper.GetChildrenCount(that);
for (var i = 0; i < childrenCount; i++) {
var child = VisualTreeHelper.GetChild(that, i);
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && elementName == frameworkElement.Name)
return (T) frameworkElement;
if ((frameworkElement = frameworkElement.FindChild<T>(elementName)) != null)
return (T) frameworkElement;
}
return null;
}
}
That should be working fine. I've just tested it and the title centers as it should.
if you want it truly centered, it needs to be:
HorizontalAlignment="Center"
I am using WPF datagrid from codeplex. I am using DatagridTemplateColumn and I have written datatemplates to display contents in each column.
Now I have to display some help message to a user when the any control in datagrid is focussed.
For this I thought of using adorner layer. I used ComboBox loaded event and accessed the adrorner layer of it. I then added my own adorner layer with some thing to be displayed there similar to tooltip. Below is the code.
TextBox txtBox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
if (txtBox == null)
return;
txtBox.ToolTip = comboBox.ToolTip;
AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(txtBox);
Binding bind = new Binding("IsKeyboardFocused");
bind.Converter = new KeyToVisibilityConverter();
bind.Source = txtBox;
bind.Mode = BindingMode.OneWay;
PEAdornerControl adorner = new PEAdornerControl(txtBox);
adorner.SetBinding(PEAdornerControl.VisibilityProperty, bind);
PEAdorner layer is this ::
public class PEAdornerControl : Adorner
{
Rect rect;
// base class constructor.
public PEAdornerControl(UIElement adornedElement)
: base(adornedElement)
{ }
protected override void OnRender(DrawingContext drawingContext)
{
.....
}
}
Now the problem is as follows. I am attaching screenshot of how it is looking in datagrid. If the datagrid has more than 4 rows, things are fine.Below is the screenshot
If the datagrid has less number of row, this adorner goes inside datagrid and is not visible to user. The screenshot is below
How do I get this adorner layer above the DataGrid? Please help me !!!
I looked at your question again and i think this is what you would need.
TextBox txtBox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
if (txtBox == null)
return;
txtBox.ToolTip = comboBox.ToolTip;
//this is locating the DataGrid that contains the textbox
DataGrid parent = FindParent<DataGrid>(this);
//Get the adorner for the parent
AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(parent);
Binding bind = new Binding("IsKeyboardFocused");
bind.Converter = new KeyToVisibilityConverter();
bind.Source = txtBox;
bind.Mode = BindingMode.OneWay;
PEAdornerControl adorner = new PEAdornerControl(txtBox);
adorner.SetBinding(PEAdornerControl.VisibilityProperty, bind);
The find parent method is this:
public T FindParent<T>(DependencyObject obj) where T : DepedencyObject
{
if (obj == null)
return null;
DependencyOBject parent = VisualTreeHelper.GetParent(obj);
if (parent is T)
return parent as T;
else
return FindParent<T>(parent);
}
You may need to set the position of your adorner in the OnRender method but this should work. One thing to consider though is that if your DataGrid is within another container (such as a panel, grid, etc) then you may still run into your clipping problem.
The clipping problem is due to the fact that when a container checks the layout of its children it does not normally take into account their adorners. To combat this you would possibly need to create your own control and override the MeasuerOverride(Size constraint) method.
Example:
public class MyPanel : Panel
{
protected override Size MeasureOverride(Size constraint)
{
Size toReturn = new Size();
foreach (UIElement child in this.InternalChildren)
{
//Do normal Measuring of children
foreach( UIElement achild in AdornerLayer.GetAdorners(child))
//Measure child adorners and add to return size as needed
}
return toReturn;
}
}
That code is really rough for measure but should point you in the right direction. Look at the documentation page http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.measureoverride.aspx for information about measuring child elements in a panel.
Just get the topmost AdornerLayer, instead
static AdornerLayer GetAdornerLayer(FrameworkElement adornedElement)
{
var w = Window.GetWindow(adornedElement);
var vis = w.Content as Visual;
return AdornerLayer.GetAdornerLayer(vis);
}
Also, if you have the name of your DataGrid you can get the nearest layer above it:
AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(myDataGrid);
RichTextBox is placed inside a ViewBox and zoomed to various levels 10 - 1000%. At percentages less than 100%, caret disappears at random cursor locations.
I understand that when a visual is zoomed out (compressed), it will loose pixels. Is there any way that I can stop loosing my cursor?
<Viewbox>
<RichTextBox Name="richTextBox1" Width="400" Height="400" />
</Viewbox>
FINAL EDIT:
hey there, just wanted to say, you can even get this working without reflection at all!! This is not optimized code, I'll leave that for yourself. Also this is still relying on internal stuff. So here it comes:
Codebehind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.ScaleX = scale.ScaleX;
};
}
}
public class RTBwithVisibleCaret:RichTextBox
{
private UIElement _flowDocumentView;
private AdornerLayer _adornerLayer;
private UIElement _caretSubElement;
private ScaleTransform _scaleTransform;
public RTBwithVisibleCaret()
{
LayoutUpdated += (sender, args) =>
{
if (!IsKeyboardFocused) return;
if(_adornerLayer == null)
_adornerLayer = AdornerLayer.GetAdornerLayer(_flowDocumentView);
if (_adornerLayer == null || _flowDocumentView == null) return;
if(_scaleTransform != null && _caretSubElement!= null)
{
_scaleTransform.ScaleX = 1/ScaleX;
_adornerLayer.Update(_flowDocumentView);
}
else
{
var adorners = _adornerLayer.GetAdorners(_flowDocumentView);
if(adorners == null || adorners.Length<1) return;
var caret = adorners[0];
_caretSubElement = (UIElement) VisualTreeHelper.GetChild(caret, 0);
if(!(_caretSubElement.RenderTransform is ScaleTransform))
{
_scaleTransform = new ScaleTransform(1 / ScaleX, 1);
_caretSubElement.RenderTransform = _scaleTransform;
}
}
};
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var cthost = GetTemplateChild("PART_ContentHost") as FrameworkElement;
_flowDocumentView = cthost is ScrollViewer ? (UIElement)((ScrollViewer)cthost).Content : ((Decorator)cthost).Child;
}
public double ScaleX
{
get { return (double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
public static readonly DependencyProperty ScaleXProperty =
DependencyProperty.Register("ScaleX", typeof(double), typeof(RTBwithVisibleCaret), new UIPropertyMetadata(1.0));
}
working with this XAML:
<Window x:Class="RTBinViewBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:RTBinViewBoxTest="clr-namespace:RTBinViewBoxTest" Title="MainWindow" Height="350" Width="525">
<Viewbox Height="100" x:Name="vb">
<RTBinViewBoxTest:RTBwithVisibleCaret Width="70" x:Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RTBinViewBoxTest:RTBwithVisibleCaret>
</Viewbox>
</Window>
yeah, it got me thinking when I saw, that all these are accessible through the visual tree! Instead of inheriting from RichTextBox (which was needed to get the TemplateChild) you can also traverse the VisualTree to get to that FlowDocumentView!
original post:
ok, let's look at what your options are:
as stated in my comment above: the easiest way to accomplish this whould be to have RichTextBox's content zoom instead of the RichTextBox being inside a ViewBox. You haven't answered (yet) if this would be an option.
now everything else will get complex and is more or less problematic:
you can use Moq or something similar (think Moles or so...) to replace the getter of SystemParameters.CaretWidth to accommodate for the ScaleTransform the ViewBox exerts. This has several problems! First: these Libraries are designed for use in testing scenarios and not recommended for production use. Second: you would have to set the value before the RichTextBox instantiates the Caret. That'd be tough though, as you don't know beforehand how the ViewBox scales the RichTextBox. So, this is not a good option!
the second (bad) option would be to use Reflection to get to this nice little Class System.Windows.Documents.CaretElement. You can get there through RichTextBox.TextEditor.Selection.CaretElement (you have to use Reflection as these Properties and Classes are for the most part internal sealed). As this is an Adorner you might be able to attach a ScaleTransform there that reverses the Scaling. I have to say though: this is neither tested nor recommended!
Your options are limited here and if I were you I'd go for my first guess!
EDIT:
If you really want to get down that second (bad) route you might have more luck if you apply that ScaleTransform to that adorners single child that you can get through the private field _caretElement of type CaretSubElement. If I read that code right, then that subelement is your actual Caret Visual. The main element seems to be used for drawing selection geometry. If you really want to do this, then apply that ScaleTransform there.
EDIT:
complete example to follow:
XAML:
<Window x:Class="RTBinViewBoxTest.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">
<Viewbox Height="100" x:Name="vb">
<RichTextBox Width="70" Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Viewbox>
</Window>
Codebehind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.GotFocus +=RtbOnGotFocus;
}
private void RtbOnGotFocus(object s, RoutedEventArgs routedEventArgs)
{
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.Selection.GetType().GetMethod("System.Windows.Documents.ITextSelection.UpdateCaretAndHighlight", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(
rtb.Selection, null);
var caretElement=rtb.Selection.GetType().GetProperty("CaretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(rtb.Selection, null);
if (caretElement == null)
return;
var caretSubElement = caretElement.GetType().GetField("_caretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(caretElement) as UIElement;
if (caretSubElement == null) return;
var scaleTransform = new ScaleTransform(1/scale.ScaleX, 1);
caretSubElement.RenderTransform = scaleTransform;
};
}
}
this works for me. everything said.
AFAIK you can't really solve this. ViewBox is using ScaleTransform under the covers, and ScaleTransform, when scaling down, will hide certain lines, since it cannot display everything. the ScaleTransform is not using a very advanced algorithm to do the scale,(it just does it in the fastest way possible) and I don't think you can change that..
I have a ListBox and a DockPanel. List box contains items that are supposed to be dragged onto the dock panel. I've implemented that by following this link.
There are a couple of things I do not understand though:
While dragging, all I see is a cursor. I'd like to literary see the list item I am
dragging to move around with my cursor. How do I do that?
Is the DragDropEffect property only for the different cursor design or it has a
higher purpose? :)
How do I make list item disappear from the ListBox once it is dropped onto the
DockPanel?
I'd like to enforce some animation on the items that I drag, like glow once it is
dropped. Which trigger/setter should I use for that?
Here's my code for basic dragging and dropping:
Code-behind for the ListBox part
private Point startPosition;
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPosition = e.GetPosition(null);
}
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point currentPosition;
Vector offset;
ListBox listBox;
ListBoxItem item;
Match match;
DataObject dragData;
currentPosition = e.GetPosition(null);
offset = startPosition - currentPosition;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(offset.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(offset.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the data binded to ListBoxItem object, which is "match"
listBox = sender as ListBox;
item = FindAnchestor<ListBoxItem>((DependencyObject)e.OriginalSource);
match = (Match)listBox.ItemContainerGenerator.ItemFromContainer(item);
dragData = new DataObject("match", match);
DragDrop.DoDragDrop(item, dragData, DragDropEffects.Move);
}
}
Code-behind for the DockPanel part
private void DockPanel_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent("match") ||
sender == e.Source)
{
e.Effects = DragDropEffects.None;
}
}
private void DockPanel_Drop(object sender, DragEventArgs e)
{
Match match;
DockPanel matchSlot;
ContentPresenter contentPresenter;
Binding binding;
if (e.Data.GetDataPresent("match"))
{
match = e.Data.GetData("match") as Match;
matchSlot = sender as DockPanel;
contentPresenter = new ContentPresenter();
contentPresenter.ContentTemplate = this.FindResource("MatchTemplate") as DataTemplate;
binding = new Binding();
binding.Source = match;
contentPresenter.SetBinding(ContentPresenter.ContentProperty, binding);
matchSlot.Children.Clear();
matchSlot.Children.Add(contentPresenter);
}
}
Thanks for all the help.
Ok, after a while I found some answers and discovered a few things on my own.
As for the DragDropEffect enum, it should be used for two reasons:
To distinguish if the item is moved or copied in the code. It serves like a flag and should be used most commonly like this:
if (e.DragDropEffect == DragDropEffect.Move)
{
...
}
else ...
To decorate the mouse cursor based on the enum value. This way it tells the user if he or she is moving or copying the item.
As for the drag and drop visualization here's a link to the post containing the reference which is an excellent starting point for drag and drop to build on: WPF Drag & Drop: How to literally drag an element?