Wpf 附加 属性 绑定未设置 属性
Wpf attached property binding not setting property
我正在使用这个项目的范围面板 http://www.codeproject.com/Articles/30881/Creating-an-Outlook-Calendar-Using-WPF-Part
using System;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
namespace Application
{
public class RangePanel : Panel
{
public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangePanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty BeginProperty = DependencyProperty.RegisterAttached("Begin", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty EndProperty = DependencyProperty.RegisterAttached("End", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static void SetBegin(UIElement element, double value)
{
element.SetValue(BeginProperty, value);
}
public static double GetBegin(UIElement element)
{
return (double)element.GetValue(BeginProperty);
}
public static void SetEnd(UIElement element, double value)
{
element.SetValue(EndProperty, value);
}
public static double GetEnd(UIElement element)
{
return (double)element.GetValue(EndProperty);
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
protected override Size ArrangeOverride(Size finalSize)
{
double containerRange = (Maximum - Minimum);
foreach (UIElement element in Children)
{
double begin = (double)element.GetValue(BeginProperty);
double end = (double)element.GetValue(EndProperty);
double elementRange = end - begin;
Size size = new Size
{
Width =
(Orientation == Orientation.Vertical)
? finalSize.Width
: elementRange/containerRange*finalSize.Width,
Height =
(Orientation == Orientation.Vertical)
? elementRange/containerRange*finalSize.Height
: finalSize.Height
};
Debug.Print((begin - Minimum) / containerRange * finalSize.Width + " " + (begin - Minimum) / containerRange * finalSize.Height);
Point location = new Point
{
X = (Orientation == Orientation.Vertical) ? 0 : (begin - Minimum)/containerRange*finalSize.Width,
Y = (Orientation == Orientation.Vertical) ? (begin - Minimum)/containerRange*finalSize.Height : 0
};
element.Arrange(new Rect(location, size));
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement element in Children)
{
element.Measure(availableSize);
}
double maxX = 0, maxY = 0;
foreach (UIElement element in Children)
{
if (element.DesiredSize.Width > maxX)
maxX = element.DesiredSize.Width;
if (element.DesiredSize.Height > maxY)
maxY = element.DesiredSize.Height;
}
availableSize.Width = maxX;
availableSize.Height = maxY;
return availableSize;
}
}
}
当我 运行 它时,我得到了错误
'Begin' property was already registered by 'UIElement'
指的是 begin/end 属性,但我不知道为什么。
最小值和最大值设置为静态值 0/1440,开始和结束通过绑定设置(starttime/endtime 是日期时间,已转换为自午夜以来的分钟数,我还验证了转换器的工作原理 属性) 如下
<Border BorderBrush="DarkSlateGray"
RangePanel.Begin="{Binding StartTime, Converter={StaticResource TimeToMinutes}}"
RangePanel.End="{Binding EndTime, Converter={StaticResource TimeToMinutes}}">
<TextBlock Text="{Binding AppointmentDescription}" Background="Red" />
</Border>
但是绑定不起作用,这意味着布局失败并且所有元素都堆叠在一起,因为开始始终为 0,因此位置变为 (0,0)。我已将范围缩小到没有获得 set/having 值的开始和结束属性,但我不知道为什么。
我找到了我自己的问题的答案,它在 this answer。
基本上,itemscontrol 需要通过 ItemsControl.ItemContainerStyle 设置 begin/end 属性。
这是修改后的代码片段
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="calendarControls:RangePanel.Begin" Value="{Binding StartTime, Converter={StaticResource TimeToMinutes}}" />
<Setter Property="calendarControls:RangePanel.End" Value="{Binding EndTime, Converter={StaticResource TimeToMinutes}}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkSlateGray">
<TextBlock Text="{Binding AppointmentDescription}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
现在可以按预期工作了。
我正在使用这个项目的范围面板 http://www.codeproject.com/Articles/30881/Creating-an-Outlook-Calendar-Using-WPF-Part
using System;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
namespace Application
{
public class RangePanel : Panel
{
public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangePanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty BeginProperty = DependencyProperty.RegisterAttached("Begin", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static DependencyProperty EndProperty = DependencyProperty.RegisterAttached("End", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
public static void SetBegin(UIElement element, double value)
{
element.SetValue(BeginProperty, value);
}
public static double GetBegin(UIElement element)
{
return (double)element.GetValue(BeginProperty);
}
public static void SetEnd(UIElement element, double value)
{
element.SetValue(EndProperty, value);
}
public static double GetEnd(UIElement element)
{
return (double)element.GetValue(EndProperty);
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
protected override Size ArrangeOverride(Size finalSize)
{
double containerRange = (Maximum - Minimum);
foreach (UIElement element in Children)
{
double begin = (double)element.GetValue(BeginProperty);
double end = (double)element.GetValue(EndProperty);
double elementRange = end - begin;
Size size = new Size
{
Width =
(Orientation == Orientation.Vertical)
? finalSize.Width
: elementRange/containerRange*finalSize.Width,
Height =
(Orientation == Orientation.Vertical)
? elementRange/containerRange*finalSize.Height
: finalSize.Height
};
Debug.Print((begin - Minimum) / containerRange * finalSize.Width + " " + (begin - Minimum) / containerRange * finalSize.Height);
Point location = new Point
{
X = (Orientation == Orientation.Vertical) ? 0 : (begin - Minimum)/containerRange*finalSize.Width,
Y = (Orientation == Orientation.Vertical) ? (begin - Minimum)/containerRange*finalSize.Height : 0
};
element.Arrange(new Rect(location, size));
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement element in Children)
{
element.Measure(availableSize);
}
double maxX = 0, maxY = 0;
foreach (UIElement element in Children)
{
if (element.DesiredSize.Width > maxX)
maxX = element.DesiredSize.Width;
if (element.DesiredSize.Height > maxY)
maxY = element.DesiredSize.Height;
}
availableSize.Width = maxX;
availableSize.Height = maxY;
return availableSize;
}
}
}
当我 运行 它时,我得到了错误
'Begin' property was already registered by 'UIElement'
指的是 begin/end 属性,但我不知道为什么。
最小值和最大值设置为静态值 0/1440,开始和结束通过绑定设置(starttime/endtime 是日期时间,已转换为自午夜以来的分钟数,我还验证了转换器的工作原理 属性) 如下
<Border BorderBrush="DarkSlateGray"
RangePanel.Begin="{Binding StartTime, Converter={StaticResource TimeToMinutes}}"
RangePanel.End="{Binding EndTime, Converter={StaticResource TimeToMinutes}}">
<TextBlock Text="{Binding AppointmentDescription}" Background="Red" />
</Border>
但是绑定不起作用,这意味着布局失败并且所有元素都堆叠在一起,因为开始始终为 0,因此位置变为 (0,0)。我已将范围缩小到没有获得 set/having 值的开始和结束属性,但我不知道为什么。
我找到了我自己的问题的答案,它在 this answer。
基本上,itemscontrol 需要通过 ItemsControl.ItemContainerStyle 设置 begin/end 属性。
这是修改后的代码片段
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="calendarControls:RangePanel.Begin" Value="{Binding StartTime, Converter={StaticResource TimeToMinutes}}" />
<Setter Property="calendarControls:RangePanel.End" Value="{Binding EndTime, Converter={StaticResource TimeToMinutes}}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkSlateGray">
<TextBlock Text="{Binding AppointmentDescription}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
现在可以按预期工作了。