WPF — использование CroppedBitmap в DataTemplate

Следующий xaml нормально работает внутри Window:

<Border Width="45" Height="55" CornerRadius="10" >
    <Border.Background>
        <ImageBrush>
            <ImageBrush.ImageSource>
                <CroppedBitmap Source="profile.jpg" SourceRect="0 0 45 55"/>
            </ImageBrush.ImageSource>
        </ImageBrush>    
    </Border.Background>
</Border>

Но когда я использую эквивалентный код в DataTemplate, я получаю следующую ошибку во время выполнения:

Ошибка инициализации объекта (ISupportInitialize.EndInit). Свойство "Источник" не задано. Ошибка объекта 'System.Windows.Media.Imaging.CroppedBitmap' в файле разметки.
Внутреннее исключение:
{"Свойство "Источник" не задано."}

Единственная разница в том, что у меня есть свойство Source CroppedBitmap с привязкой к данным:

<CroppedBitmap Source="{Binding Photo}" SourceRect="0 0 45 55"/>

Что дает?

ОБНОВЛЕНИЕ: согласно старому сообщению Беа Столльниц это ограничение исходного свойства CroppedBitmap, поскольку оно реализует ISupportInitialize. (Эта информация находится внизу страницы — выполните поиск по «11:29», и вы увидите).
Это все еще проблема с .Net 3.5 SP1?


person Gus Cavalcanti    schedule 10.11.2009    source источник
comment
Ссылка на блог Беа Столльниц мертва, и я не могу найти архив.   -  person StayOnTarget    schedule 16.04.2019


Ответы (2)


Когда синтаксический анализатор XAML создает CroppedBitmap, он делает следующее:

var c = new CroppedBitmap();
c.BeginInit();
c.Source = ...    OR   c.SetBinding(...
c.SourceRect = ...
c.EndInit();

EndInit() требует, чтобы Source было ненулевым.

Когда вы говорите c.Source=..., значение всегда устанавливается перед EndInit(), но если вы используете c.SetBinding(...), он пытается немедленно выполнить привязку, но обнаруживает, что DataContext еще не установлено. Поэтому он откладывает привязку на потом. Таким образом, когда вызывается EndInit(), Source по-прежнему имеет значение null.

Это объясняет, почему вам нужен преобразователь в этом сценарии.

person Ray Burns    schedule 13.11.2009
comment
Я знаю, что это очень старая тема, но у меня та же проблема. Какой преобразователь мне нужно сделать? Спасибо за любую помощь! - person PitAttack76; 25.07.2013
comment
Не могли бы вы уточнить, где нужен преобразователь? Для какого атрибута? - person StayOnTarget; 16.04.2019

Я думал, что завершу другой ответ, предоставив упомянутый преобразователь.

Теперь я использую этот конвертер, и он, кажется, работает, больше свойство Source не установлено с ошибкой.

public class CroppedBitmapConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        FormatConvertedBitmap fcb = new FormatConvertedBitmap();
        fcb.BeginInit();
        fcb.Source = new BitmapImage(new Uri((string)value));
        fcb.EndInit();
        return fcb;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
person PitAttack76    schedule 25.07.2013
comment
Упомянутый блог Bea Stollnitz больше не существует - я не знаю, где и как использовать ваш конвертер. Я пробовал <CroppedBitmap Source="{Binding PortraitPath, Converter={StaticResource croppedBitmapConverter}}" SourceRect="{Binding PortraitBounds}"/>, но все еще получаю ошибку Source свойство не установлено. Случайно не помните, как вы это сделали? - person Olson.dev; 14.07.2016