WPF의 페이지 로드 시 콤보 상자에 기본 텍스트 "--Select Team --"을 표시하는 방법
WPF 앱의 MVP 앱에는 콤보 박스가 있어 데이터베이스에서 가져온 데이터를 표시합니다.콤보 상자에 추가된 항목을 표시하기 전에 다음과 같은 기본 텍스트를 표시합니다.
" --팀 선택 --"
따라서 페이지 로드 시 텍스트가 표시되고 선택 시 텍스트가 지워지고 항목이 표시되어야 합니다.
DB에서 데이터를 선택하고 있습니다.사용자가 콤보 상자에서 항목을 선택할 때까지 기본 텍스트를 표시해야 합니다.
안내 부탁드립니다
가장 쉬운 방법은 다음과 같습니다.
<ComboBox Name="MyComboBox"
IsEditable="True"
IsReadOnly="True"
Text="-- Select Team --" />
다른 옵션을 추가해야 하는 것은 분명하지만 이것이 가장 간단한 방법입니다.
그러나 이 방법에는 콤보 상자 내의 텍스트는 편집할 수 없지만 선택할 수 있다는 단점이 있습니다.그러나 지금까지 제가 발견한 모든 대안들의 낮은 품질과 복잡성을 고려할 때, 이것이 아마도 가장 좋은 선택일 것입니다.
할 수 .IValueConverter
.
<Grid>
<ComboBox
x:Name="comboBox1"
ItemsSource="{Binding MyItemSource}" />
<TextBlock
Visibility="{Binding SelectedItem, ElementName=comboBox1, Converter={StaticResource NullToVisibilityConverter}}"
IsHitTestVisible="False"
Text="... Select Team ..." />
</Grid>
여기 다시 사용할 수 있는 컨버터 클래스가 있습니다.
public class NullToVisibilityConverter : IValueConverter
{
#region Implementation of IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
마지막으로 리소스 섹션에서 컨버터를 선언해야 합니다.
<Converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
여기서 Converters는 컨버터 클래스를 배치한 장소입니다.예를 들어 다음과 같습니다.
xmlns:Converters="clr-namespace:MyProject.Resources.Converters"
이 접근법의 가장 좋은 점은 뒤에 있는 코드에 코드가 반복되지 않는다는 것입니다.
Tri Q의 답변은 마음에 들지만, 이러한 가치 변환기를 사용하는 것은 매우 귀찮습니다.PaulB는 이벤트 핸들러를 사용했지만, 그것도 불필요합니다.순수 XAML 솔루션은 다음과 같습니다.
<ContentControl Content="{Binding YourChoices}">
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid>
<ComboBox x:Name="cb" ItemsSource="{Binding}"/>
<TextBlock x:Name="tb" Text="Select Something" IsHitTestVisible="False" Visibility="Hidden"/>
</Grid>
<DataTemplate.Triggers>
<Trigger SourceName="cb" Property="SelectedItem" Value="{x:Null}">
<Setter TargetName="tb" Property="Visibility" Value="Visible"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
아무도 순수한 자말 용액이 복잡해야 한다고 말하지 않았다.여기 텍스트 상자에 데이터 트리거가 하나 있는 간단한 예가 있습니다.여백과 원하는 위치
<Grid>
<ComboBox x:Name="mybox" ItemsSource="{Binding}"/>
<TextBlock Text="Select Something" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=mybox,Path=SelectedItem}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
★★IsEditable="True"
ComboBox
「 」. 「 」가 됩니다.Text
의 of의 ComboBox
.
직접 지원되는지는 알 수 없지만 선택 항목이 null이 아닌 경우 레이블로 콤보를 덮어쓰고 숨김으로 설정할 수 있습니다.
예:
<Grid>
<ComboBox Text="Test" Height="23" SelectionChanged="comboBox1_SelectionChanged" Name="comboBox1" VerticalAlignment="Top" ItemsSource="{Binding Source=ABCD}" />
<TextBlock IsHitTestVisible="False" Margin="10,5,0,0" Name="txtSelectTeam" Foreground="Gray" Text="Select Team ..."></TextBlock>
</Grid>
그런 다음 선택한 핸들러에서 변경...
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
txtSelectTeam.Visibility = comboBox1.SelectedItem == null ? Visibility.Visible : Visibility.Hidden;
}
IceForge의 답변을 바탕으로 재사용 가능한 솔루션을 준비했습니다.
xaml 스타일:
<Style x:Key="ComboBoxSelectOverlay" TargetType="TextBlock">
<Setter Property="Grid.ZIndex" Value="10"/>
<Setter Property="Foreground" Value="{x:Static SystemColors.GrayTextBrush}"/>
<Setter Property="Margin" Value="6,4,10,0"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
사용 예:
<Grid>
<ComboBox x:Name="cmb"
ItemsSource="{Binding Teams}"
SelectedItem="{Binding SelectedTeam}"/>
<TextBlock DataContext="{Binding ElementName=cmb,Path=SelectedItem}"
Text=" -- Select Team --"
Style="{StaticResource ComboBoxSelectOverlay}"/>
</Grid>
콤보 박스로는 시도하지 않았지만 다른 컨트롤로도 작동했습니다.
그는 여기에 비침을 표시하기 위해 장식 레이어를 사용합니다.
HappyNomad의 솔루션은 매우 좋았고, 결국 이 약간 다른 솔루션에 도달하는 데 도움을 주었습니다.
<ComboBox x:Name="ComboBoxUploadProject"
Grid.Row="2"
Width="200"
Height="23"
Margin="64,0,0,0"
ItemsSource="{Binding projectList}"
SelectedValue ="{Binding projectSelect}"
DisplayMemberPath="projectName"
SelectedValuePath="projectId"
>
<ComboBox.Template>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ComboBox x:Name="cb"
DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}}"
SelectedValue ="{Binding SelectedValue, RelativeSource={RelativeSource TemplatedParent}}"
DisplayMemberPath="projectName"
SelectedValuePath="projectId"
/>
<TextBlock x:Name="tb" Text="Select Item..." Margin="3,3,0,0" IsHitTestVisible="False" Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="cb" Property="SelectedItem" Value="{x:Null}">
<Setter TargetName="tb" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ComboBox.Template>
</ComboBox>
가장 쉬운 방법은 CompositeCollection을 사용하여 데이터베이스에서 기본 텍스트와 데이터를 ComboBox에서 직접 병합하는 것입니다.
<ComboBox x:Name="SelectTeamComboBox" SelectedIndex="0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem Visibility="Collapsed">-- Select Team --</ComboBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource ResourceKey=MyComboOptions}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
또한 리소스에서 StaticResource를 정의하여 CollectionContainer의 직접 바인딩이 제대로 작동하지 않기 때문에 ComboBox 옵션을 DataContext에 바인딩합니다.
<Window.Resources>
<CollectionViewSource Source="{Binding}" x:Key="MyComboOptions" />
</Window.Resources>
이렇게 하면 xaml에서만 ComboBox 옵션을 정의할 수 있습니다.
<ComboBox x:Name="SelectTeamComboBox" SelectedIndex="0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem Visibility="Collapsed">-- Select Team --</ComboBoxItem>
<ComboBoxItem >Option 1</ComboBoxItem>
<ComboBoxItem >Option 2</ComboBoxItem>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
다음 사항을 권장합니다.
동작을 정의하다
public static class ComboBoxBehaviors
{
public static readonly DependencyProperty DefaultTextProperty =
DependencyProperty.RegisterAttached("DefaultText", typeof(String), typeof(ComboBox), new PropertyMetadata(null));
public static String GetDefaultText(DependencyObject obj)
{
return (String)obj.GetValue(DefaultTextProperty);
}
public static void SetDefaultText(DependencyObject obj, String value)
{
var combo = (ComboBox)obj;
RefreshDefaultText(combo, value);
combo.SelectionChanged += (sender, _) => RefreshDefaultText((ComboBox)sender, GetDefaultText((ComboBox)sender));
obj.SetValue(DefaultTextProperty, value);
}
static void RefreshDefaultText(ComboBox combo, string text)
{
// if item is selected and DefaultText is set
if (combo.SelectedIndex == -1 && !String.IsNullOrEmpty(text))
{
// Show DefaultText
var visual = new TextBlock()
{
FontStyle = FontStyles.Italic,
Text = text,
Foreground = Brushes.Gray
};
combo.Background = new VisualBrush(visual)
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Center,
Transform = new TranslateTransform(3, 0)
};
}
else
{
// Hide DefaultText
combo.Background = null;
}
}
}
사용자 동작
<ComboBox Name="cmb" Margin="72,121,0,0" VerticalAlignment="Top"
local:ComboBoxBehaviors.DefaultText="-- Select Team --"/>
IceForge의 대답은 매우 비슷했고, AFIK가 이 문제에 대한 가장 쉬운 해결책입니다.그러나 동작하고 있지 않기 때문에(적어도, 텍스트는 실제로 표시되지 않습니다.
결국 콤보 상자의 선택한 항목이 null이 아닌 경우 텍스트 블록의 "가시성" 속성을 "숨김"으로 설정할 수 없습니다. 기본적으로는 트리거에서 null이 아님을 선택할 수 없으므로 트리거와 동일한 위치에서 XAML의 Setter를 사용하여 이러한 방식으로 설정해야 합니다.
다음은 그를 기반으로 한 실제 솔루션입니다. 누락된 세터는 트리거 바로 앞에 배치됩니다.
<ComboBox x:Name="combo"/>
<TextBlock Text="--Select Team--" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Setters>
<Setter Property="Visibility" Value="Hidden"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo,Path=SelectedItem}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
베스트 프랙티스가 아닙니다.하지만 잘 작동한다...
<ComboBox GotFocus="Focused" x:Name="combobox1" HorizontalAlignment="Left" Margin="8,29,0,0" VerticalAlignment="Top" Width="128" Height="117"/>
코드 배후에 있다
public partial class MainWindow : Window
{
bool clearonce = true;
bool fillonce = true;
public MainWindow()
{
this.InitializeComponent();
combobox1.Items.Insert(0, " -- Select Team --");
combobox1.SelectedIndex = 0;
}
private void Focused(object sender, RoutedEventArgs e)
{
if(clearonce)
{
combobox1.Items.Clear();
clearonce = false;
}
if (fillonce)
{
//fill the combobox items here
for (int i = 0; i < 10; i++)
{
combobox1.Items.Insert(i, i);
}
fillonce = false;
}
}
}
이 게시물에 언급된 워터마크가 이 경우에 적합하다고 생각합니다.
약간의 코드가 필요하지만 콤보박스나 텍스트박스(패스워드박스도 포함)에 재사용할 수 있으므로 이 방법을 선호합니다.
프로젝트에서 Is Null Converter 클래스를 사용하고 있는데 효과가 있었습니다.여기에 c#의 코드가 있습니다.사용된 트리거는 null이 아닌 값을 지원하지 않기 때문에 Converter라는 이름의 폴더를 만들고 그 폴더에 이 클래스를 추가합니다.Is Null Converter는 이 작업을 수행합니다.
public class IsNullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value == null);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullConverter can only be used OneWay.");
}
}
xaml 파일에 네임스페이스를 이렇게 추가합니다.
xmlns:Converters="clr-namespace:TymeSheet.Converter"
수단
xmlns:Converters="clr-namespace:YourProjectName.Converter"
리소스 아래의 이 행을 사용하여 xaml 코드를 통해 사용할 수 있도록 합니다.
<Converters:IsNullConverter x:Key="isNullConverter" />
이것은 xaml 코드입니다.여기서 트리거를 사용했기 때문에 콤보박스에서 항목을 선택할 때마다 텍스트의 가시성이 거짓이 됩니다.
<TextBlock Text="Select Project" IsHitTestVisible="False" FontFamily="/TimeSheet;component/Resources/#Open Sans" FontSize="14" Canvas.Right="191" Canvas.Top="22">
<TextBlock.Resources>
<Converters:IsNullConverter x:Key="isNullConverter"/>
</TextBlock.Resources>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ProjectComboBox,Path=SelectedItem,Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
//XAML 드 am
// View Model 코드
private CategoryModel _SelectedCategory;
public CategoryModel SelectedCategory
{
get { return _SelectedCategory; }
set
{
_SelectedCategory = value;
OnPropertyChanged("SelectedCategory");
}
}
private ObservableCollection<CategoryModel> _Categories;
public ObservableCollection<CategoryModel> Categories
{
get { return _Categories; }
set
{
_Categories = value;
_Categories.Insert(0, new CategoryModel()
{
CategoryId = 0,
CategoryName = " -- Select Category -- "
});
SelectedCategory = _Categories[0];
OnPropertyChanged("Categories");
}
}
조금 늦었지만..
보다 간단한 방법은 IsDummy=true 매개 변수를 사용하여 목록에 더미 데이터 항목을 추가하고 HitTestVisible이 아니며 HitTestVisible의 높이가 1픽셀(Converter 사용)이므로 표시되지 않도록 하는 것입니다.
Selection Changed에 등록하고 인덱스를 더미 아이템인덱스로 설정합니다.
이것은 매력적으로 작동하며, 이렇게 하면 콤보 박스의 스타일과 색상, 그리고 당신의 어플리케이션 테마를 망치지 않습니다.
InitializeComponent()
yourcombobox.text=" -- Select Team --";
위의 코드는 이를 실현하는 가장 간단한 방법을 보여줍니다.창 로드 후 를 사용하여 콤보 상자의 텍스트를 선언합니다.콤보 상자의 텍스트 속성입니다.이것은 DatePicker, Textbox 및 기타 컨트롤로도 확장할 수 있습니다.
편집: 아래 코멘트에 따르면 이는 해결책이 아닙니다.어떻게 작동시켰는지 확실치 않고 프로젝트도 확인할 수 없습니다.
최신 XAML에 대한 답변을 업데이트해야 합니다.
이 SO 질문을 찾아 이 질문에 대한 해결책을 찾아본 결과 업데이트된 XAML 사양에는 단순한 솔루션이 포함되어 있습니다.
이제 "Placeholder"라는 속성을 사용하여 이 작업을 수행할 수 있습니다.다음과 같이 간단합니다(Visual Studio 2015).
<ComboBox x:Name="Selection" PlaceholderText="Select...">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</ComboBox>
콤보박스를 이렇게 코드 뒤에 있는 데이터베이스 데이터로 바인딩하기 전에 이 작업을 수행했습니다.
Combobox.Items.Add("-- Select Team --");
Combobox.SelectedIndex = 0;
콤보 박스 위에 라벨을 붙입니다.
레이블의 내용을 콤보 상자 텍스트 속성에 바인딩합니다.
콤보 상자의 불투명도를 0, Opacity=0으로 설정합니다.
콤보 상자에 기본 텍스트 쓰기 텍스트 속성
<ComboBox Name="cb" Text="--Select Team--" Opacity="0" Height="40" Width="140" > <ComboBoxItem Content="Manchester United" /> <ComboBoxItem Content="Lester" /> </ComboBox> </Grid>
이것은 오래된 것이지만, MVVM 스타일의 아이디어가 있습니다.Stylet MVVM 프레임워크를 사용하고 있습니다.표시 내용:
<UserControl x:Class="ComboBoxWithPlaceholderTextView"
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:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
>
<Grid>
<ComboBox
ItemsSource="{Binding ItemsSource}"
SelectedItem="{Binding SelectedItem}"
DropDownOpened="{s:Action DropDownOpened}"
DropDownClosed="{s:Action DropDownClosed}"
IsDropDownOpen="{Binding IsDropDownOpened}"
/>
</Grid>
[ View Model ]에 표시됩니다.
public class ComboBoxWithPlaceholderTextViewModel : Screen
{
private List<string> _itemsSource;
private string _placeholderText;
private string _selectedItem;
private bool _isDropDownOpened;
public bool IsDropDownOpened
{
get => _isDropDownOpened;
set
{
if (value == _isDropDownOpened)
{
return;
}
SetAndNotify(ref _isDropDownOpened, value);
}
}
public string SelectedItem
{
get
{
return _selectedItem;
}
set
{
SetAndNotify(ref _selectedItem, value);
}
}
public string PlaceholderText
{
get { return _placeholderText; }
set
{
if (value == _placeholderText)
{
return;
}
SetAndNotify(ref _placeholderText, value);
}
}
public List<string> ItemsSource
{
get { return _itemsSource; }
set
{
SetAndNotify(ref _itemsSource, value);
if (!IsDropDownOpened && (string.IsNullOrEmpty(SelectedItem) || !SelectedItem.Equals(PlaceholderText)))
{
ItemsSource.Insert(0, PlaceholderText);
SelectedItem = ItemsSource[0];
}
}
}
public void DropDownOpened()
{
ItemsSource.RemoveAt(0);
SelectedItem = null;
}
public void DropDownClosed()
{
if (SelectedItem is null)
{
ItemsSource.Insert(0, PlaceholderText);
SelectedItem = ItemsSource[0];
}
}
}
이렇게 하면 텍스트가 콤보에서 이스케이프되는지 여부는 신경 쓰지 않아도 되지만 자리 표시자 텍스트가 선택되었는지 여부는 신경 써야 합니다.
IsEditable 속성만 true로 설정합니다.
<ComboBox Name="comboBox1"
Text="--Select Team--"
IsEditable="true" <---- that's all!
IsReadOnly="true"/>
이게 좀 오래된 건 알지만, 이런 방식은 어때?
<DataTemplate x:Key="italComboWM">
<TextBlock FontSize="11" FontFamily="Segoe UI" FontStyle="Italic" Text="--Select an item--" />
</DataTemplate>
<ComboBox EmptySelectionBoxTemplate="{StaticResource italComboWM}" />
언급URL : https://stackoverflow.com/questions/1426050/how-to-display-default-text-select-team-in-combo-box-on-pageload-in-wpf
'source' 카테고리의 다른 글
PropertyChanged 이벤트는 항상 null입니다. (0) | 2023.04.19 |
---|---|
마우스 커서로 WPF 창을 최대화하려면 어떻게 해야 합니까? (0) | 2023.04.19 |
한 열에서 구별 선택 (0) | 2023.04.19 |
MS Word 테이블을 Excel 시트로 내보내기 위한 매크로 (0) | 2023.04.19 |
Swift: 스위치 문의 테스트 클래스 유형 (0) | 2023.04.19 |