Хост изображений WPF с центрированием и отсечкой
Я чувствую, что мне могут понадобиться некоторые конвертеры, но это то, что я хочу сделать. Я хочу один элемент управления изображения (так как он находится в шаблоне данных, который связан с реальными данными) со следующими параметрами.
- Сосредоточьтесь на расстоянии 90х90 (без растяжения).
- Имеют круговое отсечение радиусом 40 пикселей (как горизонтальное, так и вертикальное).
- Если изображение> 90x90, оно должно центрироваться в пространстве 90x90 и обрезать круг 40x40 от середины.
- Если изображение <90x90, оно должно центрироваться в пределах пространства 90x90. Обтравочный круг не должен иметь никакого эффекта, поскольку все изображение содержится в области клипа.
У меня есть код XAML ниже. Это работает, как и ожидалось, для изображений размером точно 90x90 (то есть они не растягиваются, они центрируют изображение и отсечение работает). Для изображений> 90x90 отсечение работает правильно, но изображение не центрируется. Для изображений <90x90 изображение центрируется, но отсечение, кажется, помещает изображение в верхнюю левую область содержимого изображения, поэтому отсечение обрезает верхнюю левую часть изображения.
<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>
Я могу избавиться от второй проблемы (маленькое обрезание изображения), обернув его в Grid и переместив его туда, но большие объекты не центрируются:
<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>
3 ответа
В итоге мне пришлось просто удалить свойства "Ширина" и "Высота" из стиля изображения. Глядя на это с помощью WPF Snoop, изображение теперь больше, чем содержащая Grid, но, поскольку Grid имеет фиксированный размер, он центрируется на этом.
<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>
Самый простой способ, который я нашел для центрирования, обрезки и изображения, - это использовать другой элемент, такой как Rectangle, а затем заполнить его ImageBrush. Например:
<Rectangle>
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding SomeUriPropertyOrOther}"
Stretch="UniformToFill"/>
</Rectangle.Fill>
</Rectangle>
Это делает центрирование и отсечение. (Не имеет значения для Stretch == Fill and Uniform, я думаю.)
Используйте ImageBrush в вашей Datatemplate. Тогда вы можете рисовать в эллипс, а не использовать отсечение.
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>
Код
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; }
}
Результат