DependencyProperty不使用值

时间:2016-08-22 14:37:15

标签: c# wpf dependency-properties

我使用DependencyProperty(dp)在C#和WPF中编写了一个近乎工作的控件。我可以从控件的dp返回数据但我在设置初始值时遇到问题。该控件是最终产品的简化版本,用于此处给出。

模特

public class modelMain:ViewModelBase
{
    public modelMain(string colName, string hexval)
    {
        ColorName = colName;
        HexValue = hexval;
    }

    string colorName;
    public string ColorName
    {
        get { return colorName; }
        set { SetProperty(ref this.colorName, value, "ColorName"); }
    }

    string hexValue;
    public string HexValue
    {
        get { return hexValue; }
        set { SetProperty(ref this.hexValue, value, "HexValue"); }
    }
}

ViewModel

public class viewModelMain:ViewModelBase
{
    ObservableCollection<modelMain> val = new ObservableCollection<modelMain>();
    public ObservableCollection<modelMain> ColorsList
    {
        get { return val; }
        set { SetProperty(ref this.val, value, "ColorsList"); }
    }


    modelMain selectedColor;
    public modelMain SelectedColour
    {          
        get{return selectedColor;}
        set { SetProperty(ref this.selectedColor, value, "SelectedColour"); }
    }

    public void SetCurrentColor(modelMain col)
    {
        SelectedColour = this.val.Where(x => x.ColorName == col.ColorName).FirstOrDefault(); 
    }

    public viewModelMain()
    {
        val.Add(new modelMain("Red", "#FF0000"));
        val.Add(new modelMain("Blue", "#0000FF"));
        val.Add(new modelMain("Green", "#008000"));
        val.Add(new modelMain("Yellow", "#FFFFE0"));
    }
}

XAML

<Grid>
    <ComboBox x:Name="cboValue"
              SelectionChanged="cboValue_SelectionChanged"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch"
              ItemsSource="{Binding ColorList, RelativeSource={RelativeSource AncestorType=UserControl}}"
              SelectedValue="{Binding ColorsList.SelectedColor, RelativeSource={RelativeSource AncestorType=UserControl}}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Width="10"
                               Height="10"
                               Margin="5"
                               Background="{Binding ColorName}"/>
                    <TextBlock Width="35"
                               Height="15"
                               Margin="5"
                               Text="{Binding ColorName}"/>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>


</Grid>

背后的代码

    public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    public ObservableCollection<modelMain> ColorList
    {
        get { return colorList; }
        set { colorList = value; }
    }


    public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register(
        "SelectedColor",
        typeof(modelMain),
        typeof(UserControl1),
        new FrameworkPropertyMetadata(
            null, 
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            new PropertyChangedCallback(OnSelectedColorChanged),
            new CoerceValueCallback(CoerceSelectedColorCallback)));


    private static void OnSelectedColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        UserControl1 uc = (UserControl1)d;
        uc.SelectedColor = (modelMain)e.NewValue;
    }

    private static object CoerceSelectedColorCallback(DependencyObject d, object value)
    {
        return (modelMain)value;
    }


    public modelMain SelectedColor
    {
        get { return (modelMain)GetValue(SelectedColorProperty); }
        set { SetValue(SelectedColorProperty, value); }
    }

    private void cboValue_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var dat = sender as ComboBox;
        SelectedColor = (modelMain)dat.SelectedValue;
    }

}

我可以完成大部分工作,所以当我更改颜色时,dp会触发OnSelectedColorChanged,这样就可以了。我在初始化之后设置了DataContext。但是当我在测试表单中使用类型为modelMain的数据绑定时,没有任何反应。

我怀疑这个问题出现在代码中,但经过几个小时的阅读,在任意数量的网站上阅读主题后,我得出的结论是文档缺乏或位于显而易见的地方。我理想的解决方案是指向该信息的位置,并简要说明其原因和方式。给一个人一条鱼或教他钓鱼等等。 Stack Overflow几乎是我提出问题的最后一个地方,所以如果没有在这里记录搜索,请不要惊讶,但如果那些喜欢说不想要努力证明的人请问:@)

我如何使用并绑定到控件

<AControl:UserControl1 x:Name="cboBob" HorizontalAlignment="Left" Margin="100,118,0,0" VerticalAlignment="Top" Width="200" SelectedColor="{Binding Selected}" Height="29"/>

这个类绑定到

    public class viewModelBinding :ViewModelBase
{
    modelMain sel = new modelMain("Red", "#FF0000");
    public modelMain Selected
    {
        get { return sel; }
        set { SetProperty(ref this.sel, value, "Selected"); }
    }
}

继承的ViewModelBase中有大部分正常的东西,包括INotifyPropertyChanged和IDisposable等。

我将控制权改为

    <Grid>
    <ComboBox x:Name="cboValue"
              SelectionChanged="cboValue_SelectionChanged"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch"
              ItemsSource="{Binding ColorsList.ColorList, RelativeSource={RelativeSource AncestorType=UserControl}}"
              SelectedValue="{Binding ColorsList.SelectedColor, RelativeSource={RelativeSource AncestorType=UserControl}}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Width="10"
                               Height="10"
                               Margin="5"
                               Background="{Binding ColorName}"/>
                    <TextBlock Width="35"
                               Height="15"
                               Margin="5"
                               Text="{Binding ColorName}"/>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox> 
</Grid>

并以这种方式改变了代码

        public UserControl1()
    {
        InitializeComponent();
        //DataContext = new viewModelMain();
    }

    ObservableCollection<modelMain> colorList = new viewModelMain().ColorsList;
    public ObservableCollection<modelMain> ColorList
    {
        get { return colorList; }
        set { colorList = value; }
    }

colorList集合按预期填充,但控件中的列表不会。为什么会这样?我知道删除DataContext打破了链接,但我曾想过使用提供的相同进程可以工作。给出的示例非常简单,这稍微复杂一些,但不是那么复杂。

主要的Windows代码

<AControl:UserControl1 x:Name="cboBob" HorizontalAlignment="Left" Margin="100,118,0,0" VerticalAlignment="Top" Width="200" Height="29" SelectedColor="{Binding Path=BeSelected, Mode=OneWayToSource}"/>

背后的代码

        public MainWindow()
    {
        InitializeComponent();
        DataContext = new viewModelBinding();
        BeSelected =  new modelMain("Yellow", "#FFFFE0");
    }

    public modelMain BeSelected
    { 
        get { return ((viewModelBinding)DataContext).Selected; }
        set { ((viewModelBinding)DataContext).Selected = value; }
    }

用于主窗口的视图模型。

    public class viewModelBinding :ViewModelBase
{
    modelMain sel = new modelMain("Red", "#FF0000");
    public modelMain Selected
    {
        get { return sel; }
        set { SetProperty(ref this.sel, value, "Selected"); }
    }
}

我终于找到了问题的根源。克莱门斯,我要感谢我为这项技术提供了巨大的支持。剩下的问题是克莱门斯提供的例子中没有预见到的问题。这些示例中的假设是我将传递系统类型而不是用户定义的类型。这个问题的解决方案是使用IEquatable,允许传入值。

0 个答案:

没有答案