我有ComBoxBox和CheckBoxes项目。 当用户选中或取消选中复选框时,我希望所选值显示在以逗号分隔的ContentPresenter中。 目前我已经覆盖了ContentPresenter:
<ContentPresenter x:Name="ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
ContentTemplate="{StaticResource SelectedOperationsText}"/>
默认情况下,ContentPresenter是ComboBox样式的一部分。 有关如何实现此功能的任何提示?
ComboBox ItemTemplate的实现如下:
<DataTemplate x:Key="ComboItemTemplate">
<Grid HorizontalAlignment="Left">
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}"/>
</Grid>
</DataTemplate>
答案 0 :(得分:3)
此解决方案并不理想(例如,您可以为从组合框继承的控件创建自定义控件模板),但它可以正常工作。
的Xaml
<my:MyComboBox Width="180" ItemsSource="{Binding TestItems}" Text="{Binding SelectedItemsText}">
<my:MyComboBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Text}"/>
</Grid>
</DataTemplate>
</my:MyComboBox.ItemTemplate>
</my:MyComboBox>
组合框的黑客:
public class MyComboBox : ComboBox
{
private ContentPresenter selectedContent;
public MyComboBox()
{
this.DefaultStyleKey = typeof(ComboBox);
}
public override void OnApplyTemplate()
{
this.selectedContent = this.GetTemplateChild("ContentPresenter") as ContentPresenter;
this.RefreshContent();
base.OnApplyTemplate();
this.SelectionChanged += (s, e) =>
{
//Cancel selection
this.SelectedItem = null;
this.RefreshContent();
};
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MyComboBox),
new PropertyMetadata(null, new PropertyChangedCallback((s,e)=>((MyComboBox)s).RefreshContent())));
private void RefreshContent()
{
if (this.selectedContent != null)
{
var tb = (TextBlock)this.selectedContent.Content;
tb.Text = this.Text;
}
}
}
MainViewModel
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
this.InitializeTestItems();
}
public void InitializeTestItems()
{
this.TestItems = new List<TestItemModel>{
new TestItemModel{IsChecked=true, Text="first"},
new TestItemModel{IsChecked=false, Text="second"},
new TestItemModel{IsChecked=false, Text="third"}};
this.RefreshSelectedItemsText();
foreach (var item in this.TestItems)
item.CheckChanged += (s, e) => this.RefreshSelectedItemsText();
}
private void RefreshSelectedItemsText()
{
SelectedItemsText = string.Join(", ", this.TestItems.Where(ti => ti.IsChecked).Select(ti => ti.Text));
}
public List<TestItemModel> TestItems { get; set; }
private string selectedItemsText;
public string SelectedItemsText
{
get { return selectedItemsText; }
set
{
selectedItemsText = value;
OnPropertyChanged("SelectedItemsText");
}
}
}
4.ItemViewModel
public class TestItemModel
{
private bool isChecked;
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
if (CheckChanged != null)
CheckChanged(this, null);
}
}
public string Text { get; set; }
public event EventHandler<EventArgs> CheckChanged;
}
答案 1 :(得分:0)
我不明白你对“ContentPresenter”的意思。
如果你想要一个包含选定项目列表的combox框,我可以解释我的儿子(不在SO中)是如何做到的:
他将一个带有ComboBox的网格后跟一个TextBlock。 ComboBox的ItemTemplate包含一个复选框,其中包含Checked和UnChecked事件的处理程序。在这些事件中,他根据复选框的选定状态重新计算TextBlock的Text属性。 这是XAML:
<Grid Name="LayoutRoot">
<ComboBox ItemsSource="{Binding Path=SitesList}" Name="CBsites" DropDownOpened="ComboBox_DropDownOpened" DropDownClosed="ComboBox_DropDownClosed">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Path=Location}" Checked="SiteCheckBox_Checked" Unchecked="SiteCheckBox_Unchecked" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Name="TXTselected" IsHitTestVisible="False" VerticalAlignment="Center" Margin="6,0,0,0" />
</Grid>
我认为没有TextBlock就可以做到。希望这可以让你朝着正确的方向前进。
答案 2 :(得分:0)
我在这里创建了一个codeplex项目:codeplex受到这篇博客的启发和其他一些项目,请检查并改进它等等。希望这或类似的东西能够找到它进入工具包的方式..
我更喜欢在绑定数据中不需要选择布尔值,所以我带来了一个可绑定的SelectedItems