Reputation: 3227
I feel like I may need some converters, but this is what I want to do. I want a single Image control (since it is in a data template that is bound to real data) with the following parameters.
I have my XAML code below. This works as expected for pictures that are exactly 90x90 (i.e. they don't stretch, they center the image and the clipping works). For images > 90x90, the clipping works correctly but the image is not getting centered. For images < 90x90, the image gets centered but the clipping seems to place the image in the top-left area of the Image content so, the clipping clips the top-left portion of the image.
<Style x:Key="ImageStyle">
<Setter Property="Width" Value="90" />
<Setter Property="Height" Value="90" />
<Setter Property="Stretch" Value="None" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Clip">
<Setter.Value>
<EllipseGeometry Center="45,45" RadiusX="40" RadiusY="40" />
</Setter.Value>
</Setter>
</Style>
<Grid>
<!-- Other Stuff -->
<Image Source="{Binding ImagePath}" Style="{StaticResource ImageStyle}" />
</Grid>
I can get rid of the second issue (small image clipping) by wrapping in a Grid and moving the clipping there, but large stuff doesn't center:
<Grid>
<!-- Other Stuff -->
<Grid Width="90" Height="90">
<Grid.Clip>
<EllipseGeometry Center="45,45" RadiusX="40" RadiusY="40" />
</Grid.Clip>
<Image Source="{Binding ImagePath}" Style="{StaticResource ImageStyle}" />
</Grid>
</Grid>
Upvotes: 4
Views: 6487
Reputation: 5498
The easiest way I've found to center and clip and image is to use a different element, such as a Rectangle, then fill it with an ImageBrush. For example:
<Rectangle>
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding SomeUriPropertyOrOther}"
Stretch="UniformToFill"/>
</Rectangle.Fill>
</Rectangle>
This does centering and clipping. (Irrelevant for Stretch == Fill and Uniform, I guess.)
Upvotes: 3
Reputation: 3227
I ended up having to just remove the Width and Height properties from the Image Style. Looking at it with WPF Snoop, the image is now bigger than the containing Grid but since the Grid has a fixed size, it centers itself on that.
<Style x:Key="ImageStyle">
<Setter Property="Stretch" Value="None" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Grid>
<!-- Other Stuff -->
<Grid Width="90" Height="90">
<Grid.Clip>
<EllipseGeometry Center="45,45" RadiusX="40" RadiusY="40" />
</Grid.Clip>
<Image Source="{Binding ImagePath}" Style="{StaticResource ImageStyle}" />
</Grid>
</Grid>
Upvotes: 10
Reputation: 7037
Use an ImageBrush in your Datatemplate. Then you can paint into an Ellipse, and not use clipping.
XAML
<Grid>
<ListBox ItemsSource='{Binding}'>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width='90' Height='90' Background='Yellow'>
<Ellipse Width='40'
Height='40'>
<Ellipse.Fill>
<ImageBrush ImageSource='{Binding ImagePath}'
Stretch='None' />
</Ellipse.Fill>
</Ellipse>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code
public partial class Window4 : Window {
public Window4() {
InitializeComponent();
var data = new List<DemoData>();
data.Add(new DemoData { Header="Large Image", ImagePath="flower.png"});
data.Add(new DemoData { Header = "Medium Image", ImagePath = "flower_med.png" });
data.Add(new DemoData { Header = "Small Image", ImagePath = "flower_small.png" });
this.DataContext = data;
}
}
internal class DemoData {
public string Header { get; set; }
public string ImagePath { get; set; }
}
Result
Upvotes: 0