IT

WPF의 페이지로드시 콤보 상자에 기본 텍스트 "--Select Team-"을 표시하는 방법은 무엇입니까?

lottoking 2020. 8. 24. 20:36
반응형

WPF의 페이지로드시 콤보 상자에 기본 텍스트 "--Select Team-"을 표시하는 방법은 무엇입니까?


WPF 앱의 MVP 앱에는 데이터베이스에서 데이터베이스에서 데이터를 표시하는 것이 있습니다. 콤보 상자에 항목을 추가하기 전에 다음과 같은 기본 텍스트를 표시하고 싶습니다.

"-팀 선택-"

페이지로드시 표시되고 선택시 텍스트가 지워지고 항목이 표시됩니다.

DB에서 데이터를 선택하고 있습니다. 사용자가 콤보 상자에서 항목을 선택해야 할 때 기본 텍스트를 표시합니다.

나를 안내 해주세요


이 작업을 수행하는 가장 쉬운 방법은 다음과 같습니다.

<ComboBox Name="MyComboBox"
 IsEditable="True"
 IsReadOnly="True"
 Text="-- Select Team --" />

분명히 다른 옵션을 추가해야한다는 것이 아마도 가장 간단한 방법 일 것입니다.

그러나이 방법에는 한 가지 문제가 있습니다. 콤보 상자 내부의 텍스트는 편집 할 수 없지만 여전히 선택할 수 있습니다. 그러나 지금까지 모든 대안의 품질과 점수가 낮기 때문에 이것이 아마도 최고의 옵션 일 것입니다.


.NET Framework를 사용하여 코드 내부 코드없이이 작업을 수행 할 수 있습니다 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" />

변환기는 변환기 클래스를 배치 한 위치입니다. 예 :

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>

아무도 순수한 xaml 솔루션이 복잡하다고 말하지 않습니다. 다음은 텍스트 상자에 1 개의 데이터 트리거가있는 간단한 것입니다. 원하는대로 여백 및 위치

<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>

ComboBox 요소에 IsEditable = "True"를 설정합니다. ComboBox의 Text 속성이 표시됩니다.


직접 지원 모드는 모르겠지만 콤보를 레이블로 장비하고 선택이 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;
}

콤보 상자로 시도하지 다른 컨트롤과 함께 작동했습니다 ...

ageektrapped 블로그 포스트

여기에서 표시기 레이어를 사용하여 워터 마크를 표시합니다.


를 기반으로 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>

그리고 Resources에서 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의 답변 은 매우 가깝고 AFAIK 가이 문제에 대한 가장 쉬운 해결입니다. 그러나 작동하지 않아서 문장을 놓쳤습니다.

결국 콤보 상자의 선택 항목이 null이 아닐 때 숨겨 지도록 TextBlock의 "Visibility"속성을 "Hidden"으로 선택할 수 없습니다. 트리거 와 동일한 위치에서 XAML의 세터를 사용하여 트리거 에서 null이 아닌지 확인할 수이 없기 때문에 기본적으로 설정해야 우리합니다 .

다음은 트리거 바로 앞에 놓인 누락 된 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>

편집 : 아래 의견에 따라 해결책이 아닙니다. 내가 어떻게 작동하는지 확실하지 않습니다.

최신 XAML에 대한이 답변을 업데이트 할 때입니다.

이 질문에 대한 해결책을 찾기 위해이 질문을 질문 다음 업데이트 된 XAML 사양에 대한 해결책이 있음을 발견했습니다.

이제 "자리 표시 자"라는 속성을 사용하여이 작업을 수행 할 수 있습니다. 다음과 같이 간단합니다 (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 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;
            }           
    }
}

이 게시물에서 언급 한 워터 마크 가이 경우에 잘 작동 할 생각합니다.

약간의 코드가 필요하지만 모든 콤보 상자 또는 텍스트 상자 (심지어 암호 상자)에 다시 사용할 수 있으므로이 방법을 선호합니다.


내 프로젝트에서 IsNullConverter 클래스를 사용하고 있는데 저에게 그렇습니다. 여기에 C #의 코드가 있습니다. 변환기라는 폴더를 만들고 해당 폴더 에이 클래스를 추가합니다. 사용 된 트리거가 null이 아닌 값을 지원하지 않습니다 IsNullConverter가 그렇게합니다.

 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 코드

// ViewModel 코드

    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 매개 변수를 사용하여 더미 데이터 항목을 목록에 추가하고 HitTestVisable이 아니고 높이가 1 픽셀 (변환기를 사용하여)인지 확인하여 표시되지 않도록하는 것입니다.

SelectionChanged에 등록하고 그 안에 인덱스를 더미 항목 인덱스로 설정하십시오.

매력처럼 작동하며 이렇게하면 ComboBox 또는 응용 프로그램 테마의 스타일과 색상이 엉망이되지 않습니다.


InitializeComponent()
yourcombobox.text=" -- Select Team --";

위의 코드는이를 달성하는 가장 간단한 방법을 보여줍니다. 창로드 후 콤보 상자의 .Text 속성을 사용하여 콤보 상자의 텍스트를 선언합니다. 이것은 DatePicker, Textbox 및 기타 컨트롤로 확장 될 수 있습니다.


다음과 같이 코드 숨김에서 데이터베이스의 데이터로 콤보 상자를 바인딩하기 전에 수행했습니다.

Combobox.Items.Add("-- Select Team --");
Combobox.SelectedIndex = 0;

해결 방법
1. 콤보 상자 위에 레이블을 붙입니다.
2. 레이블 내용을 콤보 상자 Text 속성에 바인딩합니다.
3. 콤보 박스의 불투명도를 0, Opacity = 0으로 설정합니다.
4. 콤보 상자 Text 속성에 기본 텍스트 쓰기

 <Grid>
        <Label Content="{Binding ElementName=cb, Path=Text}" 
         VerticalContentAlignment="Center"
         HorizontalContentAlignment="Center"
         Height="{Binding ElementName=cb, Path=Height}"
         Width="{Binding ElementName=cb, Path=Width}"/>

         <ComboBox Name="cb"
           Text="--Select Team--" Opacity="0" 
           Height="40" Width="140" >
            <ComboBoxItem Content="Manchester United" />
            <ComboBoxItem Content="Lester" />
        </ComboBox>
    </Grid>

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

반응형