Skip to content

Commit f3cad3e

Browse files
committed
Preventing binding leaks for CornerRadius
1 parent 5df7796 commit f3cad3e

File tree

2 files changed

+85
-25
lines changed

2 files changed

+85
-25
lines changed

Fluent.Ribbon/Converters/CornerRadiusConverter.cs

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,46 @@
88
/// <summary>
99
/// Used to convert from four double values to <see cref="CornerRadius"/>
1010
/// </summary>
11-
public class CornerRadiusConverter : IMultiValueConverter
11+
[ValueConversion(typeof(CornerRadius), typeof(CornerRadius))]
12+
[ValueConversion(typeof(IConvertible[]), typeof(CornerRadius))]
13+
public class CornerRadiusConverter : IValueConverter, IMultiValueConverter
1214
{
15+
/// <inheritdoc />
16+
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
17+
{
18+
var valuesToExtract = parameter is CornerRadiusPart cornerRadiusValue
19+
? cornerRadiusValue
20+
: CornerRadiusPart.All;
21+
22+
var source = (CornerRadius)value!;
23+
24+
var topLeft = valuesToExtract.HasFlag(CornerRadiusPart.TopLeft) ? source.TopLeft : 0;
25+
var topRight = valuesToExtract.HasFlag(CornerRadiusPart.TopRight) ? source.TopRight : 0;
26+
var bottomRight = valuesToExtract.HasFlag(CornerRadiusPart.BottomRight) ? source.BottomRight : 0;
27+
var bottomLeft = valuesToExtract.HasFlag(CornerRadiusPart.BottomLeft) ? source.BottomLeft : 0;
28+
29+
return new CornerRadius(topLeft, topRight, bottomRight, bottomLeft);
30+
}
31+
32+
/// <inheritdoc />
33+
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
34+
{
35+
throw new NotImplementedException();
36+
}
37+
1338
#region Implementation of IMultiValueConverter
1439

1540
/// <inheritdoc />
1641
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
1742
{
18-
var topLeft = TryConvertSingleValue(values[0]);
19-
var topRight = TryConvertSingleValue(values[1]);
20-
var bottomRight = TryConvertSingleValue(values[2]);
21-
var bottomLeft = TryConvertSingleValue(values[3]);
43+
var valuesToExtract = parameter is CornerRadiusPart cornerRadiusValue
44+
? cornerRadiusValue
45+
: CornerRadiusPart.All;
46+
47+
var topLeft = valuesToExtract.HasFlag(CornerRadiusPart.TopLeft) ? TryConvertSingleValue(values[0]) : 0;
48+
var topRight = valuesToExtract.HasFlag(CornerRadiusPart.TopRight) ? TryConvertSingleValue(values[1]) : 0;
49+
var bottomRight = valuesToExtract.HasFlag(CornerRadiusPart.BottomRight) ? TryConvertSingleValue(values[2]) : 0;
50+
var bottomLeft = valuesToExtract.HasFlag(CornerRadiusPart.BottomLeft) ? TryConvertSingleValue(values[3]) : 0;
2251

2352
return new CornerRadius(topLeft, topRight, bottomRight, bottomLeft);
2453
}
@@ -42,4 +71,41 @@ private static double TryConvertSingleValue(object value)
4271
return 0;
4372
}
4473
}
74+
}
75+
76+
/// <summary>
77+
/// Defines parts of a <see cref="CornerRadius"/>.
78+
/// </summary>
79+
[Flags]
80+
public enum CornerRadiusPart
81+
{
82+
/// <summary>
83+
/// None.
84+
/// </summary>
85+
None = 0,
86+
87+
/// <summary>
88+
/// Top left.
89+
/// </summary>
90+
TopLeft = 1 << 1,
91+
92+
/// <summary>
93+
/// Top right.
94+
/// </summary>
95+
TopRight = 1 << 2,
96+
97+
/// <summary>
98+
/// Bottom right.
99+
/// </summary>
100+
BottomRight = 1 << 3,
101+
102+
/// <summary>
103+
/// Bottom left.
104+
/// </summary>
105+
BottomLeft = 1 << 4,
106+
107+
/// <summary>
108+
/// All parts.
109+
/// </summary>
110+
All = TopLeft | TopRight | BottomRight | BottomLeft
45111
}

Fluent.Ribbon/Themes/Controls/RibbonScrollViewer.xaml

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,13 @@
6262
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
6363
Focusable="false">
6464
<Fluent:RibbonProperties.CornerRadius>
65-
<MultiBinding Converter="{x:Static converters:StaticConverters.CornerRadiusConverter}">
66-
<Binding FallbackValue="0"
67-
Path="(Fluent:RibbonProperties.CornerRadius).TopLeft"
68-
RelativeSource="{RelativeSource TemplatedParent}" />
69-
<Binding Source="0" />
70-
<Binding Source="0" />
71-
<Binding FallbackValue="0"
72-
Path="(Fluent:RibbonProperties.CornerRadius).BottomLeft"
73-
RelativeSource="{RelativeSource TemplatedParent}" />
74-
</MultiBinding>
65+
<Binding Converter="{x:Static converters:StaticConverters.CornerRadiusConverter}"
66+
RelativeSource="{RelativeSource TemplatedParent}"
67+
Path="(Fluent:RibbonProperties.CornerRadius)">
68+
<Binding.ConverterParameter>
69+
<converters:CornerRadiusPart>TopLeft,BottomLeft</converters:CornerRadiusPart>
70+
</Binding.ConverterParameter>
71+
</Binding>
7572
</Fluent:RibbonProperties.CornerRadius>
7673
<RepeatButton.Visibility>
7774
<MultiBinding Converter="{StaticResource Fluent.Ribbon.Converters.MenuScrollingVisibilityConverter}"
@@ -99,16 +96,13 @@
9996
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
10097
Focusable="false">
10198
<Fluent:RibbonProperties.CornerRadius>
102-
<MultiBinding Converter="{x:Static converters:StaticConverters.CornerRadiusConverter}">
103-
<Binding Source="0" />
104-
<Binding FallbackValue="0"
105-
Path="(Fluent:RibbonProperties.CornerRadius).TopRight"
106-
RelativeSource="{RelativeSource TemplatedParent}" />
107-
<Binding FallbackValue="0"
108-
Path="(Fluent:RibbonProperties.CornerRadius).BottomRight"
109-
RelativeSource="{RelativeSource TemplatedParent}" />
110-
<Binding Source="0" />
111-
</MultiBinding>
99+
<Binding Converter="{x:Static converters:StaticConverters.CornerRadiusConverter}"
100+
RelativeSource="{RelativeSource TemplatedParent}"
101+
Path="(Fluent:RibbonProperties.CornerRadius)">
102+
<Binding.ConverterParameter>
103+
<converters:CornerRadiusPart>TopRight,BottomRight</converters:CornerRadiusPart>
104+
</Binding.ConverterParameter>
105+
</Binding>
112106
</Fluent:RibbonProperties.CornerRadius>
113107
<RepeatButton.Visibility>
114108
<MultiBinding Converter="{StaticResource Fluent.Ribbon.Converters.MenuScrollingVisibilityConverter}"

0 commit comments

Comments
 (0)