문제

첫 번째 심각한 WPF 프로젝트에 들어갑니다. 평평한 기본 컨트롤이 많이없는 것 같습니다. 구체적으로, 나는 숫자 updown 컨트롤을 찾고 있습니다. 내가 놓친 밴드 릴리스가 있었습니까? 정말 내 자신의 통제를 쓰고 싶지 않다고 생각합니다.

WindowsFormhost를 사용하고 Winform CTL을 Plop하고 싶지 않습니다. 레거시 쓰레기없이 완전히 WPF가되기를 원합니다.

감사

도움이 되었습니까?

해결책

간단히 사용하십시오 IntegerUpDown 제어 WPF 툴킷이 확장되었습니다다음과 같이 사용할 수 있습니다.

  1. 다음 네임 스페이스를 XAML에 추가하십시오.

    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"

  2. 제어 사용을 원하는 XAML에서 :

    <xctk:IntegerUpDown Name="myUpDownControl" />

다른 팁

나는 내 자신을 만들었다.

XAML

<StackPanel Orientation="Horizontal">
    <TextBox x:Name="txtNum" x:FieldModifier="private" Margin="5,5,0,5" Width="50" Text="0" TextChanged="txtNum_TextChanged" />
    <Button x:Name="cmdUp" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="cmdUp_Click" />
    <Button x:Name="cmdDown" x:FieldModifier="private" Margin="0,5,0,5"  Content="˅" Width="20" Click="cmdDown_Click" />
</StackPanel>

그리고 뒤에있는 코드

private int _numValue = 0;

public int NumValue
{
    get {  return _numValue; }
    set
    {
        _numValue = value;
        txtNum.Text = value.ToString();
    }
}

public NumberUpDown()
{
    InitializeComponent();
    txtNum.Text = _numValue.ToString();
}

private void cmdUp_Click(object sender, RoutedEventArgs e)
{
    NumValue++;
}

private void cmdDown_Click(object sender, RoutedEventArgs e)
{
    NumValue--;
}

private void txtNum_TextChanged(object sender, TextChangedEventArgs e)
{
    if (txtNum == null)
    {
        return;
    }

    if (!int.TryParse(txtNum.Text, out _numValue))
        txtNum.Text = _numValue.ToString();
}

이것은 위아래로 키 잡기가있는 내 자신의 Usercontrol의 예입니다.

XAML 코드 :

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="13" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="13" />
        <RowDefinition Height="13" />
    </Grid.RowDefinitions>
    <TextBox Name="NUDTextBox"  Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" TextAlignment="Right" PreviewKeyDown="NUDTextBox_PreviewKeyDown" PreviewKeyUp="NUDTextBox_PreviewKeyUp" TextChanged="NUDTextBox_TextChanged"/>
    <RepeatButton Name="NUDButtonUP"  Grid.Column="1" Grid.Row="0" FontSize="8" FontFamily="Marlett" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Click="NUDButtonUP_Click">5</RepeatButton>
    <RepeatButton Name="NUDButtonDown"  Grid.Column="1" Grid.Row="1" FontSize="8"  FontFamily="Marlett" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="13" VerticalAlignment="Bottom" Click="NUDButtonDown_Click">6</RepeatButton>
</Grid>

그리고 코드 :

public partial class NumericUpDown : UserControl
{
    int minvalue = 0, 
        maxvalue = 100,
        startvalue = 10;
    public NumericUpDown()
    {
        InitializeComponent();
        NUDTextBox.Text = startvalue.ToString();
    }

    private void NUDButtonUP_Click(object sender, RoutedEventArgs e)
    {
        int number;
        if (NUDTextBox.Text != "") number = Convert.ToInt32(NUDTextBox.Text);
        else number = 0;
        if (number < maxvalue)
            NUDTextBox.Text = Convert.ToString(number + 1); 
    }

    private void NUDButtonDown_Click(object sender, RoutedEventArgs e)
    {
        int number;
        if (NUDTextBox.Text != "") number = Convert.ToInt32(NUDTextBox.Text);
        else number = 0;
        if (number > minvalue)
            NUDTextBox.Text = Convert.ToString(number - 1); 
    }

    private void NUDTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {

        if (e.Key == Key.Up)
        {
            NUDButtonUP.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
            typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(NUDButtonUP, new object[] { true }); 
        }


        if (e.Key == Key.Down)
        {
            NUDButtonDown.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
            typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(NUDButtonDown, new object[] { true }); 
        }
    }

    private void NUDTextBox_PreviewKeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Up)
            typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(NUDButtonUP, new object[] { false });

        if (e.Key == Key.Down)
            typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(NUDButtonDown, new object[] { false });
    }

    private void NUDTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        int number = 0;
        if (NUDTextBox.Text!="")
            if (!int.TryParse(NUDTextBox.Text, out number)) NUDTextBox.Text = startvalue.ToString();
        if (number > maxvalue)  NUDTextBox.Text = maxvalue.ToString();
        if (number < minvalue) NUDTextBox.Text = minvalue.ToString();
        NUDTextBox.SelectionStart = NUDTextBox.Text.Length;

    }

}
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:numericButton2">


    <Style TargetType="{x:Type local:NumericUpDown}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:NumericUpDown}">              
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <RepeatButton Grid.Row="0" Name="Part_UpButton"/>
                            <ContentPresenter Grid.Row="1"></ContentPresenter>
                            <RepeatButton Grid.Row="2" Name="Part_DownButton"/>
                        </Grid>                  
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

    <Window x:Class="numericButton2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:numericButton2"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <local:NumericUpDown Margin="181,94,253,161" x:Name="ufuk" StepValue="4" Minimum="0" Maximum="20">            
            </local:NumericUpDown>
            <TextBlock Margin="211,112,279,0" Text="{Binding ElementName=ufuk, Path=Value}" Height="20" VerticalAlignment="Top"></TextBlock>
        </Grid>
    </Window>
public class NumericUpDown : Control
{
    private RepeatButton _UpButton;
    private RepeatButton _DownButton;
    public readonly static DependencyProperty MaximumProperty;
    public readonly static DependencyProperty MinimumProperty;
    public readonly static DependencyProperty ValueProperty;
    public readonly static DependencyProperty StepProperty;   
    static NumericUpDown()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
        MaximumProperty = DependencyProperty.Register("Maximum", typeof(int), typeof(NumericUpDown), new UIPropertyMetadata(10));
        MinimumProperty = DependencyProperty.Register("Minimum", typeof(int), typeof(NumericUpDown), new UIPropertyMetadata(0));
        StepProperty = DependencyProperty.Register("StepValue", typeof(int), typeof(NumericUpDown), new FrameworkPropertyMetadata(5));
        ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown), new FrameworkPropertyMetadata(0));
    }
    #region DpAccessior
    public int Maximum
    {
        get { return (int)GetValue(MaximumProperty); }
        set { SetValue(MaximumProperty, value); }
    }
    public int Minimum
    {
        get { return (int)GetValue(MinimumProperty); }
        set { SetValue(MinimumProperty, value); }
    }
    public int Value
    {
        get { return (int)GetValue(ValueProperty); }
        set { SetCurrentValue(ValueProperty, value); }
    }
    public int StepValue
    {
        get { return (int)GetValue(StepProperty); }
        set { SetValue(StepProperty, value); }
    }
    #endregion
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        _UpButton = Template.FindName("Part_UpButton", this) as RepeatButton;
        _DownButton = Template.FindName("Part_DownButton", this) as RepeatButton;
        _UpButton.Click += _UpButton_Click;
        _DownButton.Click += _DownButton_Click;
    }

    void _DownButton_Click(object sender, RoutedEventArgs e)
    {
        if (Value > Minimum)
        {
            Value -= StepValue;
            if (Value < Minimum)
                Value = Minimum;
        }
    }

    void _UpButton_Click(object sender, RoutedEventArgs e)
    {
        if (Value < Maximum)
        {
            Value += StepValue;
            if (Value > Maximum)
                Value = Maximum;
        }
    }

}

주어진 답변은 괜찮습니다. 그러나 마우스가 컨트롤을 떠날 때 버튼이 자동 숨기기를 원했습니다. 다음은 내 코드를 기반으로합니다 베르핀 위의 답변 :

스타일

<Style TargetType="{x:Type v:IntegerTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type v:IntegerTextBox}">
                    <Grid Background="Transparent">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <TextBox Name="tbmain" Grid.ColumnSpan="2" Grid.RowSpan="2"
                                 Text="{Binding Value, Mode=TwoWay, NotifyOnSourceUpdated=True, 
                            NotifyOnValidationError=True, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type v:IntegerTextBox}}}" 
                                               Style="{StaticResource ValidationStyle}" />
                        <RepeatButton Name="PART_UpButton" BorderThickness="0" Grid.Column="1" Grid.Row="0"
                                      Width="13" Background="Transparent">
                            <Path Fill="Black" Data="M 0 3 L 6 3 L 3 0 Z"/>
                        </RepeatButton>
                        <RepeatButton Name="PART_DownButton" BorderThickness="0" Grid.Column="1" Grid.Row="1"
                                      Width="13" Background="Transparent">
                            <Path Fill="Black" Data="M 0 0 L 3 3 L 6 0 Z"/>
                        </RepeatButton>

                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"  Value="False">
                            <Setter Property="Visibility" TargetName="PART_UpButton" Value="Collapsed"/>
                            <Setter Property="Visibility" TargetName="PART_DownButton" Value="Collapsed"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

암호

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

    public int Maximum
    {
        get { return (int)GetValue(MaximumProperty); }
        set { SetValue(MaximumProperty, value); }
    }
    public readonly static DependencyProperty MaximumProperty = DependencyProperty.Register(
        "Maximum", typeof(int), typeof(IntegerTextBox), new UIPropertyMetadata(int.MaxValue));



    public int Minimum
    {
        get { return (int)GetValue(MinimumProperty); }
        set { SetValue(MinimumProperty, value); }
    }
    public readonly static DependencyProperty MinimumProperty = DependencyProperty.Register(
        "Minimum", typeof(int), typeof(IntegerTextBox), new UIPropertyMetadata(int.MinValue));


    public int Value
    {
        get { return (int)GetValue(ValueProperty); }
        set { SetCurrentValue(ValueProperty, value); }
    }
    public readonly static DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(int), typeof(IntegerTextBox), new UIPropertyMetadata(0, (o,e)=>
        {
            IntegerTextBox tb = (IntegerTextBox)o;
            tb.RaiseValueChangedEvent(e);
        }));

    public event EventHandler<DependencyPropertyChangedEventArgs> ValueChanged;
    private void RaiseValueChangedEvent(DependencyPropertyChangedEventArgs e)
    {
        ValueChanged?.Invoke(this, e);
    }


    public int Step
    {
        get { return (int)GetValue(StepProperty); }
        set { SetValue(StepProperty, value); }
    }
    public readonly static DependencyProperty StepProperty = DependencyProperty.Register(
        "Step", typeof(int), typeof(IntegerTextBox), new UIPropertyMetadata(1));



    RepeatButton _UpButton;
    RepeatButton _DownButton;
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        _UpButton = Template.FindName("PART_UpButton", this) as RepeatButton;
        _DownButton = Template.FindName("PART_DownButton", this) as RepeatButton;
        _UpButton.Click += btup_Click;
        _DownButton.Click += btdown_Click;
    }


    private void btup_Click(object sender, RoutedEventArgs e)
    {
        if (Value < Maximum)
        {
            Value += Step;
            if (Value > Maximum)
                Value = Maximum;
        }
    }

    private void btdown_Click(object sender, RoutedEventArgs e)
    {
        if (Value > Minimum)
        {
            Value -= Step;
            if (Value < Minimum)
                Value = Minimum;
        }
    }

}

사용 VerticalScrollBar 이랑 TextBlock WPF의 제어. 뒤에 코드에서 다음 코드를 추가하십시오.

생성자에서 스크롤 바의 이벤트 핸들러를 정의합니다.

scrollBar1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(scrollBar1_ValueChanged);
scrollBar1.Minimum = 0;
scrollBar1.Maximum = 1;
scrollBar1.SmallChange = 0.1;

그런 다음 이벤트 핸들러에서 다음을 추가합니다.

void scrollBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    FteHolderText.Text = scrollBar1.Value.ToString();
}

내 코드의 원래 스 니펫은 다음과 같습니다. 필요한 변경을 수행합니다. :)

public NewProjectPlan()
{
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(NewProjectPlan_Loaded);

    scrollBar1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(scrollBar1_ValueChanged);
    scrollBar1.Minimum = 0;
    scrollBar1.Maximum = 1;
    scrollBar1.SmallChange = 0.1;

    // etc...
}

void scrollBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    FteHolderText.Text = scrollBar1.Value.ToString();
}

당신은 나에 의해 작성된 WPF에 대해 NumericUpdown 컨트롤을 사용할 수 있습니다. WPFControls 도서관.

9 년의 질문에 계속 답변 한 것에 대해 사과드립니다.

나는 @Micheal의 답변을 따르고 있으며 작동합니다.

컨트롤 요소처럼 드래그 앤 드롭 할 수있는 usercontrol로 수행합니다. Nuget의 MaterialDesign 테마를 사용하여 Chevron 아이콘과 버튼 파급 효과를 얻습니다.

수정 된 Micheal의 러닝 숫자는 다음과 같습니다.

enter image description here

사용자 제어 코드 :-

templatenumericupdown.xaml

<UserControl x:Class="UserControlTemplate.TemplateNumericUpDown"
             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:local="clr-namespace:UserControlTemplate"
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             mc:Ignorable="d" MinHeight="48">
    <Grid Background="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="60"/>
        </Grid.ColumnDefinitions>
        <TextBox x:Name="txtNum" x:FieldModifier="private" Text="{Binding Path=NumValue}" TextChanged="TxtNum_TextChanged" FontSize="36" BorderThickness="0" VerticalAlignment="Center" Padding="5,0"/>
        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="30*"/>
                <RowDefinition Height="30*"/>
            </Grid.RowDefinitions>
            <Grid Background="#FF673AB7">
                <Viewbox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="Auto" Width="Auto">
                    <materialDesign:PackIcon Kind="ChevronUp" Foreground="White" Height="32.941" Width="32"/>
                </Viewbox>
                <Button x:Name="cmdUp" x:FieldModifier="private" Click="CmdUp_Click" Height="Auto" BorderBrush="{x:Null}" Background="{x:Null}"/>
            </Grid>
            <Grid Grid.Row="1" Background="#FF673AB7">
                <Viewbox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="Auto" Width="Auto">
                    <materialDesign:PackIcon Kind="ChevronDown" Foreground="White" Height="32.942" Width="32"/>
                </Viewbox>
                <Button x:Name="cmdDown" x:FieldModifier="private" Click="CmdDown_Click" Height="Auto" BorderBrush="{x:Null}" Background="{x:Null}"/>
            </Grid>
        </Grid>
    </Grid>
</UserControl>

templatenumericupdown.cs

using System.Windows;
using System.Windows.Controls;

namespace UserControlTemplate
{
    /// <summary>
    /// Interaction logic for TemplateNumericUpDown.xaml
    /// </summary>
    public partial class TemplateNumericUpDown : UserControl
    {
        private int _numValue = 0;
        public TemplateNumericUpDown()
        {
            InitializeComponent();
            txtNum.Text = _numValue.ToString();
        }
        public int NumValue
        {
            get { return _numValue; }
            set
            {
                if (value >= 0)
                {
                    _numValue = value;
                    txtNum.Text = value.ToString();
                }
            }
        }

        private void CmdUp_Click(object sender, RoutedEventArgs e)
        {
            NumValue++;
        }

        private void CmdDown_Click(object sender, RoutedEventArgs e)
        {
            NumValue--;
        }

        private void TxtNum_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (txtNum == null)
            {
                return;
            }

            if (!int.TryParse(txtNum.Text, out _numValue))
                txtNum.Text = _numValue.ToString();
        }
    }
}

mypagedesign.xaml에서 drag and drop을 만들었습니다. <UserControlTemplate:TemplateNumericUpDown HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100"/>

enter image description here

템플릿에서 값을 얻으려면 사용합니다.

string Value1 = JournalNumStart.NumValue;
string Value2 = JournalNumEnd.NumValue;

나는 Fontsize 요소를 기반으로 컨트롤의 높이를 바인딩하는 데 아직 좋은 기술이 아니므로 USERCONTROL에서 페이지에서 FONTSIZE를 수동으로 설정했습니다.

** 참고 :- 프로그램에서 아카이브로 "아치형"이름을 변경했습니다 =)

순진한 솔루션이 있지만 유용합니다. 코드는 다음과 같습니다.

<Grid Name="TVGrid" Background="#7F000000">  <ScrollBar Background="Black" Orientation="Vertical" Height="35" HorizontalAlignment="Left" Margin="215,254,0,0" Minimum="0" Maximum="10" LargeChange="10" Value="{Binding ElementName=channeltext2, Path=Text}" x:Name="scroll" VerticalAlignment="Top" Width="12" RenderTransformOrigin="0.5,0.5" ValueChanged="scroll_ValueChanged" >  
        <ScrollBar.RenderTransform>  
            <TransformGroup>  
                <ScaleTransform/>  
                <SkewTransform/>  
                <RotateTransform Angle="-180"/>  
                <TranslateTransform/>  
            </TransformGroup>  
        </ScrollBar.RenderTransform>  
    </ScrollBar>  
    <TextBox Name="channeltext" HorizontalContentAlignment="Center" FontSize="20"  Background="Black" Foreground="White" Height="35" HorizontalAlignment="Left" Margin="147,254,0,0" VerticalAlignment="Top" Width="53" Text="0" />  
    <TextBox Name="channeltext2" Visibility="Hidden" HorizontalContentAlignment="Center" FontSize="20"  Background="Black" Foreground="White" Height="35" HorizontalAlignment="Left" Margin="147,254,0,0" VerticalAlignment="Top" Width="53" Text="0" />  </Grid>  

다음은 다양한 입력 방법 (마우스 드래그, 마우스 휠, 커서 키, 텍스트 상자 편집)을 갖는 또 다른 오픈 소스 컨트롤입니다. 많은 데이터 유형 및 사용 사례를 지원합니다.

https://github.com/dirkster99/numericupdownlib

샘플을 수행하는 실용적인 것 :

-오른쪽을 클릭하십시오 프로젝트 (솔루션 아래), "Nuget 패키지 관리 ..."를 선택하십시오.

-메뉴를 클릭합니다 검색 "wpftoolkit"에 대한 탭 검색, 선택 "Extended.Wpf.Toolkit"

-설치하십시오!

-오른쪽 사용자 컨트롤을 클릭하십시오 공구 상자, "탭 추가 .."를 선택하고 "WPF 툴킷"이름을 지정합니다.

-오른쪽 새 "WPF 툴킷"탭을 클릭하고 "항목 선택 ..."를 선택하십시오.

-메뉴에서 "찾아보기 ..."버튼을 클릭하고 Nugets DLL 폴더를 찾으십시오....\packages\Extended.Wpf.Toolkit.3.5.0\lib\net40\*.dll"

일부 DLL에 대한 경고는 사용자 컨트롤을 포함하지 않을 수 있습니다!

준비가 된 :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top