I have this issue with ComboBox that uses IEnumerable<Brush>
as ItemsSource; the problem lies when I (programmatically) try to set SelectedItem. Here is the code that describes the problem:
private readonly List<Brush> colors_;
private Brush white_;
ViewModelConstructor()
{
colors_ = (from p in brushes_type.GetProperties()
select (Brush)converter.ConvertFromString(p.Name)).ToList();
white_ = colors_.Single(b => b.ToString() == "#FFFFFFFF");
}
public IEnumerable<Brush> Colors
{
get { return colors_; }
}
public Brush White
{
get { return white_; }
set
{
if (white_ != value)
white_ = value;
}
}
And here is xaml code:
<ComboBox ItemsSource="{Binding Path=Colors}"
SelectedItem="{Binding Path=White}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border BorderThickness="1"
BorderBrush="Black"
Width="20"
Height="12"
SnapsToDevicePixels="True"
Margin="0,0,4,0">
<Border Background="{Binding}"/>
</Border>
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
After the get on the White property is called I get an Exception: Cannot set a property on object '#FFFFFFFF' because it is in a read-only state . If i leave White (white_) as null, everything works just fine.
Using Reflector I've traced down where the problem appears to be occuring. Inside Selector.ItemSetIsSelected
, it takes the new SelectedItem
and does the following:
DependencyObject
it sets the IsSelectedProperty
on the container to true
. DependencyObject
it sets the IsSelectedProperty
on the element to true
. That second part is where the failure comes into play, the Brush
objects you've chosen are Read-Only. Because the Selector.ItemSetIsSelected
is somewhat broken in this case, you have two options.
Option 1 , you just call .Clone() on the Brush object returned from the Converter.
colors_ = (from p in typeof(Brushes).GetProperties()
select ((Brush)converter.ConvertFromString(p.Name)).Clone()).ToList();
EDIT: You should go with Option 1...Option 2 is the longwinded way to fix the problem
Option 2 , you could wrap the Brush objects into one more object:
public class BrushWrapper
{
public Brush Brush { get; set; }
}
You then update the data template paths:
<Border Background="{Binding Path=Brush}" />
and
<TextBlock Text="{Binding Path=Brush}" />
Finally, you update the ViewModel
:
private readonly List<BrushWrapper> colors_;
private BrushWrapper white_;
public ColorViewModel()
{
colors_ = (from p in typeof(Brushes).GetProperties()
select new BrushWrapper {
Brush = (Brush)converter.ConvertFromString(p.Name)
}).ToList();
white_ = colors_.Single(b => b.Brush.ToString() == "#FFFFFFFF");
}
public List<BrushWrapper> Colors
{
get { return colors_; }
}
public BrushWrapper White
{
get { return white_; }
set
{
if (white_ != value)
white_ = value;
}
}
这里只是一个黑暗的镜头(当前无法尝试),但是绑定SelectedValue而不是SelectedItem怎么样?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.