簡體   English   中英

將圖像集合分配給代碼隱藏屬性

[英]Assigning a collection of images to a code-behind property

好的,所以我已經花了幾天的時間來弄清楚XAML是如何實際處理集合的,並且每次我嘗試DependencyProperty方法時,該屬性都是null。 當我使用ObservableCollection並將其分配給XAML中的Array類型時,我收到一條消息,指出無法將ArrayExtension類型分配給集合或字典。

所以我現在正坐在一個我不知道我不知道的地方,但是我知道我的目標。

我想在代碼隱藏中為我的集合分配<Image />類型的多個元素,而且我必須能夠(最好是整數)標識集合中正在引用的“圖像”。

首選的XAML格式。

<cc:MyControl.States>
    <Image Source="{StaticResource PointBulletIconImage}" />
    <Image Source="{StaticResource PointNumberIconImage}" />
</cc:MyControl.States>

代碼隱藏所需的功能

this.Image = States[CurrentState];

您的控件應聲明一個保存ImageSource對象集合的屬性,而不是Image控件的集合,例如

public partial class MyControl : UserControl
{
    public List<ImageSource> States { get; } = new List<ImageSource>();

    ...
}

您現在可以像這樣在XAML中添加位圖資源:

<cc:MyControl>
    <cc:MyControl.States>
        <StaticResource ResourceKey="PointBulletIconImage"/>
        <StaticResource ResourceKey="PointNumberIconImage"/>
    </cc:MyControl.States>
</cc:MyControl>

MyControl的XAML將聲明一個Image控件,例如,名為“ image”

<Image x:Name="image"/>

並且您可以在后面的代碼中設置其Source屬性,如下所示:

image.Source = States[0];

好的,按照克萊門斯的建議,我弄清楚了。 問題是直到加載元素后我才“等待”。 它初始化組件,然后接受我忘記的值。 結果,分配的值尚不存在。 Clemen對ImageSource可觀察的集合使用的解決方案有效,但是我不得不等到控件加載完畢。

public ImageSource ImageSource {
        get {
            return GetValue(ImageSourceProperty) as ImageSource;
        }
        set {
            SetValue(ImageSourceProperty, value);
        }
    }
    public ObservableCollection<ImageSource> States { get; } = new ObservableCollection<ImageSource>();

    public int CurrentState { get; set; }
    public static readonly DependencyProperty ImageSourceProperty  = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(PointButton));
    public PointButton( ) {
        CurrentState = 0;
        InitializeComponent( );
        Loaded += PointButton_Loaded;
    }

    private void PointButton_Loaded(object sender, RoutedEventArgs e) {
        PreviewMouseUp += PointButton_MouseUp;
        UpdateLayout( );
        if(States == null)
            Console.WriteLine("States is null");
        else
            ImageSource = States[CurrentState];
    }

    private void PointButton_MouseUp(object sender, MouseButtonEventArgs e) {
        if(CurrentState == States.Count - 1)
            CurrentState = 0;
        else
            CurrentState += 1;
        ImageSource = States[CurrentState];
    }
}

XAML

<Button x:Class="Notes.Views.Controls.PointButton"
    x:Name="RootElement"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:Notes.Views.Controls"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300"
         >
<Button.Template>
    <ControlTemplate>
        <Image Source="{Binding ImageSource, ElementName=RootElement}" />
    </ControlTemplate>
</Button.Template>

所以,我開始工作了。 謝謝你們的回應 :)

給定您的名字,我懷疑您期望的行為是根據狀態屬性顯示一個不同的圖標,在這種情況下,您確實希望盡可能地將代碼保留在其中。

我建議使用值轉換器,在其中輸入狀態並獲取圖像源或URI,然后將圖像圖像源綁定到status屬性

這是一個看起來像這樣的完整示例注意:示例使用c#6語法

WPF:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BitmapImage x:Key="img1" UriSource="someimg1.png" />
        <BitmapImage x:Key="img2" UriSource="someimg2.png" />
        <BitmapImage x:Key="img3" UriSource="someimg3.png" />
        <BitmapImage x:Key="img4" UriSource="someimg4.png" />
        <BitmapImage x:Key="img5" UriSource="someimg5.png" />
        <local:StateImageConverter 
            x:Key="StateImageConverter"
            State1Image="{StaticResource img1}"
            State2Image="{StaticResource img2}"
            State3Image="{StaticResource img3}"
            State4Image="{StaticResource img4}"
            State5Image="{StaticResource img5}"/>
    </Window.Resources>
    <Window.DataContext>
        <local:VeiwModel x:Name="viewModel" />
    </Window.DataContext>
    <StackPanel>
        <ComboBox ItemsSource="{Binding AllStates}" SelectedValue="{Binding State}"/>
        <Image Source="{Binding State, Converter={StaticResource StateImageConverter}}" />
    </StackPanel>
</Window>

碼:

public enum States
{
    State1,
    State2,
    State3,
    State4,
    State5,
}

public class StateImageConverter : IValueConverter
{
    public ImageSource State1Image { get; set; }
    public ImageSource State2Image { get; set; }
    public ImageSource State3Image { get; set; }
    public ImageSource State4Image { get; set; }
    public ImageSource State5Image { get; set; }
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var state = value as States?;
        if(state.HasValue)
        {
            switch (state.Value)
            {
                case States.State1:
                    return State1Image;
                case States.State2:
                    return State2Image;
                case States.State3:
                    return State3Image;
                case States.State4:
                    return State4Image;
                case States.State5:
                    return State5Image;
                default:
                    throw new InvalidCastException();
            }
        }
        else
            throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //one way only
        throw new NotImplementedException();
    }
}

public class VeiwModel : System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private States state;

    public States State
    {
        get { return state; }
        set
        {
            state = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("State"));
        }
    }
    public IEnumerable<States> AllStates=> Enum.GetValues(typeof(States)).OfType< States>();

}

或者,如果您不想使用命名屬性,則使用列表的變體應類似於:

public class StateImageConverter : IValueConverter
{
    public ObservableCollection<ImageSource> Images { get; set; } = new ObservableCollection<ImageSource>();
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var state = value as States?;
        if(state.HasValue)
        {
            return Images[(int)state.Value];
        }
        else
            throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //one way only
        throw new NotImplementedException();
    }
}

定義為

<local:StateImageConverter 
            x:Key="StateImageConverter">
            <local:StateImageConverter.Images>
                <BitmapImage UriSource="someimg1.png" />
                <BitmapImage UriSource="someimg2.png" />
                <BitmapImage UriSource="someimg3.png" />
                <BitmapImage UriSource="someimg4.png" />
                <BitmapImage UriSource="someimg5.png" />
            </local:StateImageConverter.Images>
        </local:StateImageConverter>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM