您好,我制作了此XYController,当父控件DockPanel
的可见性设置为折叠时,该XYController不能正确绑定。隐藏它时,它工作正常。ThumbPosX
和ThumbPosY
应该移动,因为属性Sat
和Val
是从不同位置控制的。但是,当返回到可见时,它们总是返回到[0,0]。
public class XYController : Control
{
static XYController()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(XYController), new FrameworkPropertyMetadata(typeof(XYController)));
EventManager.RegisterClassHandler(typeof(XYController), Thumb.DragDeltaEvent, new DragDeltaEventHandler(XYController.OnThumbDragDelta));
}
#region Private Members
private const string ThumbName = "PART_Thumb";
private TranslateTransform m_thumbTransform = new TranslateTransform();
private Thumb m_thumb;
#endregion
#region Dependency Properties
public Color SelectedColor
{
get { return (Color)GetValue(SelectedColorProperty); }
set { SetValue(SelectedColorProperty, value); }
}
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register("SelectedColor", typeof(Color), typeof(XYController),
new PropertyMetadata(Colors.Transparent));
public double ThumbPosX
{
get { return (double)GetValue(ThumbPosXProperty); }
set { SetValue(ThumbPosXProperty, value); }
}
public static readonly DependencyProperty ThumbPosXProperty =
DependencyProperty.Register("ThumbPosX", typeof(double), typeof(XYController),
new PropertyMetadata(0.0, new PropertyChangedCallback(OnThumbPosChanged)));
public double ThumbPosY
{
get { return (double)GetValue(ThumbPosYProperty); }
set { SetValue(ThumbPosYProperty, value); }
}
public static readonly DependencyProperty ThumbPosYProperty =
DependencyProperty.Register("ThumbPosY", typeof(double), typeof(XYController),
new PropertyMetadata(0.0, new PropertyChangedCallback(OnThumbPosChanged)));
private static void OnThumbPosChanged(DependencyObject relatedObject, DependencyPropertyChangedEventArgs e)
{
XYController xycontroller = relatedObject as XYController;
if (xycontroller != null)
{
xycontroller.m_thumbTransform.X = xycontroller.ThumbPosX * xycontroller.ActualWidth;
xycontroller.m_thumbTransform.Y = xycontroller.ThumbPosY * xycontroller.ActualHeight;
}
}
#endregion
private void UpdatePosition(double positionX, double positionY)
{
positionX = LimitValue(positionX, ActualWidth);
positionY = LimitValue(positionY, ActualHeight);
m_thumbTransform.X = positionX;
m_thumbTransform.Y = positionY;
ThumbPosX = map(positionX, 0, ActualWidth, 0, 1);
ThumbPosY = map(positionY, 0, ActualHeight, 0, 1);
}
#region Event Handlers
private void OnThumbDragDelta(DragDeltaEventArgs e)
{
double offsetX = m_thumbTransform.X + e.HorizontalChange;
double offsetY = m_thumbTransform.Y + e.VerticalChange;
UpdatePosition(offsetX, offsetY);
}
private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
{
XYController hsvControl = sender as XYController;
hsvControl.OnThumbDragDelta(e);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (m_thumb != null)
{
Point position = e.GetPosition(this);
UpdatePosition(position.X, ActualHeight - position.Y); //Check canvas scale in style
m_thumb.RaiseEvent(e);
}
base.OnMouseLeftButtonDown(e);
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
m_thumbTransform.X = ThumbPosX * ActualWidth;
m_thumbTransform.Y = ThumbPosY * ActualHeight;
base.OnRenderSizeChanged(sizeInfo);
}
#endregion
private double LimitValue(double value, double max)
{
if (value < 0)
value = 0;
if (value > max)
value = max;
return value;
}
private double map(double value, double fromLow, double fromHigh, double toLow, double toHigh)
{
return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
m_thumb = GetTemplateChild(ThumbName) as Thumb;
if (m_thumb != null)
{
UpdatePosition(this.ThumbPosX, this.ThumbPosY);
m_thumb.RenderTransform = m_thumbTransform;
}
}
}
所以我发布了整个内容,因为我不知道缺少了什么。我还制作了“自定义滑块”,当它们合拢时它们可以正常工作。
我用这种方式:
<DockPanel
Visibility="{Binding Path=IsChecked, ElementName=HueRadio, Converter={StaticResource BoolToVisibility}}">
<local:ColorSlider
Minimum="0"
Maximum="360"
Orientation="Vertical"
Style="{DynamicResource HueSliderVertical}"
Value="{Binding Hue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="0, 4, 16, 4"
/>
<local:XYController
x:Name="HueColorControl"
Style="{StaticResource HueController}"
SelectedColor="{Binding SelectedColor}"
ThumbPosX="{Binding Sat, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ThumbPosY="{Binding Val, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="0, 4"
Height="200"
/>
</DockPanel>
只需绑定到
RadioButton
。如前所述,即使CustomControl
折叠,也是DockPanel
的ColorSlider仍在移动。我试图将可见性直接设置为XYController而不是DockPanel,但是问题仍然相同。
这里缺少什么吗?
谢谢
最佳答案
位置值的计算涉及ActualHeight
和ActualWidth
作为参数。当Visibility
设置为Visibility.Collapsed
时,这些值为0。 LimitValue
将始终返回max
参数的值(为0)。同样,OnThumbPosChanged
会将m_thumbTransform
设置为0。
您必须检测到折叠状态并立即停止计算:
private static void OnThumbPosChanged(DependencyObject relatedObject, DependencyPropertyChangedEventArgs e)
{
if (this.Visibility == Visibility.Collapsed)
{
return
}
XYController xycontroller = relatedObject as XYController;
if (xycontroller != null)
{
xycontroller.m_thumbTransform.X = xycontroller.ThumbPosX * xycontroller.ActualWidth;
xycontroller.m_thumbTransform.Y = xycontroller.ThumbPosY * xycontroller.ActualHeight;
}
}
和
private void UpdatePosition(double positionX, double positionY)
{
if (this.Visibility == Visibility.Collapsed)
{
return;
}
positionX = LimitValue(positionX, ActualWidth);
positionY = LimitValue(positionY, ActualHeight);
m_thumbTransform.X = positionX;
m_thumbTransform.Y = positionY;
ThumbPosX = map(positionX, 0, ActualWidth, 0, 1);
ThumbPosY = map(positionY, 0, ActualHeight, 0, 1);
}
将
Visibility
设置回Visibility.Visible
将恢复崩溃前的最后一个值。要立即更新位置值,您需要为PropertyChanged
属性注册一个Visibility
回调:static XYController()
{
UIElement.VisibilityProperty.OverrideMetadata(
typeof(XYController),
new PropertyMetadata(Visibility.Visible, OnVisibililtyChanged));
DefaultStyleKeyProperty.OverrideMetadata(typeof(XYController), new FrameworkPropertyMetadata(typeof(XYController)));
EventManager.RegisterClassHandler(typeof(XYController), Thumb.DragDeltaEvent, new DragDeltaEventHandler(XYController.OnThumbDragDelta));
}
private static void OnVisibililtyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Update control
OnThumbPosChanged(d, null);
// Do more updates
}
关于c# - WPF CustomControl折叠后会失去绑定(bind),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57857691/