Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将三个滑块值合并为一个Texblock文本/标签内容?_C#_Wpf_Xaml - Fatal编程技术网

C# 将三个滑块值合并为一个Texblock文本/标签内容?

C# 将三个滑块值合并为一个Texblock文本/标签内容?,c#,wpf,xaml,C#,Wpf,Xaml,我目前正在开发一个用户界面,用户可以通过三个单独的滑块选择三个值。我在滑块前面有三个文本块,用于指示特定滑块的当前值: 在.xaml中: <Label Content="Sample Selection" FontSize="16" FontStyle="Italic" FontWeight="Bold" HorizontalAlignment="Left" Margin="0,-30,0,0" VerticalAlignment="Top"/> <Label Content=

我目前正在开发一个用户界面,用户可以通过三个单独的滑块选择三个值。我在滑块前面有三个文本块,用于指示特定滑块的当前值:

在.xaml中:

<Label Content="Sample Selection" FontSize="16" FontStyle="Italic" FontWeight="Bold" HorizontalAlignment="Left" Margin="0,-30,0,0" VerticalAlignment="Top"/>
<Label Content="Patient Samples (max 64)" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontStyle="Italic"/>
<Slider x:Name="SampleAmountSlider" HorizontalAlignment="Left" Margin="181,14,0,0" VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="64" ValueChanged="SampleAmountSlider_ValueChanged" IsSnapToTickEnabled="True"/>
<TextBlock x:Name="SampleSliderValue" HorizontalAlignment="Left" Margin="165,16,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top"/>
<Label Content="Calibrators (max 7)" HorizontalAlignment="Left" Margin="10,36,0,0" VerticalAlignment="Top" FontStyle="Italic"/>
<Slider x:Name="CalAmountSlider" HorizontalAlignment="Left" Margin="181,40,0,0" VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="7" ValueChanged="CalAmountSlider_ValueChanged" IsSnapToTickEnabled="True"/>
<TextBlock x:Name="CalSliderValue" HorizontalAlignment="Left" Margin="165,42,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top"/>
<Label Content="Control Samples (max 4)" HorizontalAlignment="Left" Margin="10,62,0,0" VerticalAlignment="Top" FontStyle="Italic"/>
<Slider x:Name="ControlAmountSlider" HorizontalAlignment="Left" Margin="181,66,0,0" VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="4" ValueChanged="ControlAmountSlider_ValueChanged" IsSnapToTickEnabled="True"/>
<TextBlock x:Name="ControlSliderValue" HorizontalAlignment="Left" Margin="165,68,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top"/>
<Label Content="Total Sample Preparations Selected:" HorizontalAlignment="Left" Margin="10,105,0,0" VerticalAlignment="Top" FontWeight="Bold" FontStyle="Italic"/>
<TextBlock x:Name="TotalPrepValue" HorizontalAlignment="Left" Margin="225,110,0,0" FontWeight="Bold" FontStyle="Italic" Text="0" VerticalAlignment="Top"/>

在.xaml.cs中:

private void SampleAmountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        SampleSliderValue.Text = Math.Round(e.NewValue, 0).ToString();
    }

private void CalAmountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        CalSliderValue.Text = Math.Round(e.NewValue, 0).ToString();
    }

private void ControlAmountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        ControlSliderValue.Text = Math.Round(e.NewValue, 0).ToString();
    }
private void SampleAmountSlider\u值已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
SampleSliderValue.Text=Math.Round(例如,NewValue,0.ToString();
}
私有void CalAmountSlider_值已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
CalSliderValue.Text=Math.Round(例如NewValue,0.ToString();
}
私有void ControlAmountSlider\u值已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
ControlSliderValue.Text=Math.Round(例如NewValue,0.ToString();
}
我想要的是最后一个文本块(名为TotalPrepValue)包含患者样本量、校准器量和对照样本量的总和

我不确定我问的问题是否很多,或者事情是否不清楚(如果是,请让我知道。我会尽快回答)。 问题是,我是一个非常缺乏经验的程序员,但愿意学习!
提前感谢您的帮助

就我个人而言,我会这么做。然而,如果你喜欢的话,也请去投票@JerryNixon's,因为使用滑块代替他的例子基本上是一种重新分解,他应该得到更多的赞扬。通常我会直接告诉你,但我知道当你刚开始做一些事情的时候,一个更清晰的PoC会更有用

不管怎样,给你,一个美丽的开始

XAML

<Window.Resources>
    <local:SumConverter x:Key="MySumConverter" />
</Window.Resources>
<Grid>


    <StackPanel VerticalAlignment="Center">
        <StackPanel.Resources>            
            <Style TargetType="Slider">
                <Setter Property="Margin" Value="10"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Minimum" Value="0"/>
                <Setter Property="Maximum" Value="100"/>
            </Style>
        </StackPanel.Resources>

        <Slider x:Name="Slider1"></Slider>
        <Slider x:Name="Slider2"></Slider>
        <Slider x:Name="Slider3"></Slider>

        <TextBlock HorizontalAlignment="Center" TextAlignment="Center">
            <Run Text="{Binding Value, ElementName=Slider1}"/>
            <LineBreak/><LineBreak/>
            <Run Text="{Binding Value, ElementName=Slider2}"/>
            <LineBreak/><LineBreak/>
            <Run Text="{Binding Value, ElementName=Slider3}"/>
            <LineBreak/>
            <Run Text="______________________"/>
            <LineBreak/><LineBreak/>
            <Run>
                <Run.Text>
                    <MultiBinding Converter="{StaticResource MySumConverter}"
                                  StringFormat="{}{0:C}"
                                  FallbackValue="Error" TargetNullValue="Null">
                        <Binding Path="Value" ElementName="Slider1"/>
                        <Binding Path="Value" ElementName="Slider2"/>
                        <Binding Path="Value" ElementName="Slider3"/>
                    </MultiBinding>
                </Run.Text>
            </Run>
        </TextBlock>            

    </StackPanel>


</Grid>

希望这有帮助,干杯。

正如其他人所建议的,您可以在此场景中使用
IMultiValueConverter
。但我的观点是,虽然在其他情况下这是一个有用的工具,但在这里这是一个错误的工具。原因是,在这种情况下,它将被用来永久不适当地使用UI元素作为存储非UI数据的地方

在编写WPF程序时,如果您承诺遵循WPF打算与之一起使用的MVVM编程风格,您将得到更好的服务。术语“MVVM”字面意思是“模型、视图、视图模型”。从这个角度来看,模型和视图之间总会有特殊用途的“适配器”类型。但根据我的经验,MVVM范例的重要部分是严格地将视图逻辑与模型逻辑分开,这通常可以在没有额外的“视图模型”类型的情况下完成。这使MVVM与MVC(“模型、视图、控制器”)和MVP(“模型、视图、演示者”)处于同一组工具中

所有这些的关键是,您有一些在模型数据结构中表示的业务逻辑,这些逻辑由提供某种形式的值更改通知的类型实现(在WPF中,这里的主要机制是
INotifyPropertyChanged
),然后还可以查看完全单独表示的逻辑(在WPF中,视图大部分(并且在许多情况下完全)是用XAML声明的)

在您的示例中,这意味着我们需要一个表示您感兴趣的数据的模型数据结构:样本、校准器、控制和总准备计数。最后一个是前三个的总和。只要我们有一个类可以跟踪这些,并且在其他三个值中的任何一个发生变化时正确更新求和值ge,我们可以直接将其绑定到XAML中声明的视图,而无需使用任何C#代码

例如:

class ViewModel : INotifyPropertyChanged
{
    private int _sampleCount;
    public int SampleCount
    {
        get { return _sampleCount; }
        set { _UpdateField(ref _sampleCount, value, OnCountChanged); }
    }

    private int _calibratorCount;
    public int CalibratorCount
    {
        get { return _calibratorCount; }
        set { _UpdateField(ref _calibratorCount, value, OnCountChanged); }
    }

    private int _controlCount;
    public int ControlCount
    {
        get { return _controlCount; }
        set { _UpdateField(ref _controlCount, value, OnCountChanged); }
    }

    private int _totalPrepCount;
    public int TotalPrepCount
    {
        get { return _totalPrepCount; }
        set { _UpdateField(ref _totalPrepCount, value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnCountChanged(int previousValue)
    {
        TotalPrepCount = SampleCount + CalibratorCount + ControlCount;
    }

    protected void _UpdateField<T>(ref T field, T newValue,
        Action<T> onChangedCallback = null,
        [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, newValue))
        {
            return;
        }

        T oldValue = field;

        field = newValue;
        onChangedCallback?.Invoke(oldValue);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
(旁白:除了改变以支持MVVM方法外,我根本没有修改您的基本UI声明。我同意您需要开始熟悉的另一件事是如何利用WPF的各种布局容器和元素样式特性。但是我认为在这里介绍这些只会混淆问题。通过如果您的原始用户界面基本上完好无损,您可以只关注那些与您最初拥有的不同的东西,帮助您更好地理解数据绑定方面,而不会分心。)

在此实现中,没有任何代码添加到
MainWindow.xaml.cs
文件中。该文件中的所有内容都是对构造函数中
InitializeComponent()
的默认调用,由Visual Studio的WPF项目模板提供

另一方面,在XAML中,我将事件处理程序订阅替换为直接绑定到
Slider.Value
属性的绑定。还要注意的是
TextBlock.Text
属性也绑定到相同的属性。通过这种方式,WPF完成了在仅业务逻辑的数据结构中存储Slider值的所有繁重工作cture,然后在视图的文本字段中重新显示这些值。您会注意到WPF甚至处理各种数据类型之间的转换:视图模型存储
int
值,但滑块使用
double
,文本块当然使用
string

当然,
TotalPrepCount
字段也绑定到要显示的
TextBlock.Text
属性

最后,我将注意到,即使在您的简单示例中,您也可能需要在其他地方应用此数据绑定方法。特别是,您的滑块都有最大值,这些值都硬编码到视图中。MVVM的观点是视图不必封装任何关于业务逻辑的知识。这包括e不必知道允许值的完整范围(*)

因此,您的视图模型还可以有一个
MaxSampleCount
属性,该属性绑定到
滑块.max
属性和
标签.Content
属性。在后一种情况下,您可以使用
绑定.StringFormat
属性
class ViewModel : INotifyPropertyChanged
{
    private int _sampleCount;
    public int SampleCount
    {
        get { return _sampleCount; }
        set { _UpdateField(ref _sampleCount, value, OnCountChanged); }
    }

    private int _calibratorCount;
    public int CalibratorCount
    {
        get { return _calibratorCount; }
        set { _UpdateField(ref _calibratorCount, value, OnCountChanged); }
    }

    private int _controlCount;
    public int ControlCount
    {
        get { return _controlCount; }
        set { _UpdateField(ref _controlCount, value, OnCountChanged); }
    }

    private int _totalPrepCount;
    public int TotalPrepCount
    {
        get { return _totalPrepCount; }
        set { _UpdateField(ref _totalPrepCount, value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnCountChanged(int previousValue)
    {
        TotalPrepCount = SampleCount + CalibratorCount + ControlCount;
    }

    protected void _UpdateField<T>(ref T field, T newValue,
        Action<T> onChangedCallback = null,
        [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, newValue))
        {
            return;
        }

        T oldValue = field;

        field = newValue;
        onChangedCallback?.Invoke(oldValue);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
<Window x:Class="TestSO45170241SliderExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:l="clr-namespace:TestSO45170241SliderExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Window.DataContext>
    <l:ViewModel/>
  </Window.DataContext>

  <Grid>
    <Label Content="Sample Selection" FontSize="16" FontStyle="Italic" FontWeight="Bold"
           HorizontalAlignment="Left" Margin="0,-30,0,0" VerticalAlignment="Top"/>
    <Label Content="Patient Samples (max 64)" HorizontalAlignment="Left" Margin="10,10,0,0"
           VerticalAlignment="Top" FontStyle="Italic"/>
    <Slider HorizontalAlignment="Left" Margin="181,14,0,0"
            VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="64"
            Value="{Binding SampleCount}" IsSnapToTickEnabled="True"/>
    <TextBlock HorizontalAlignment="Left" Margin="165,16,0,0"
               TextWrapping="Wrap" Text="{Binding SampleCount}" VerticalAlignment="Top"/>
    <Label Content="Calibrators (max 7)" HorizontalAlignment="Left" Margin="10,36,0,0"
           VerticalAlignment="Top" FontStyle="Italic"/>
    <Slider HorizontalAlignment="Left" Margin="181,40,0,0"
            VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="7"
            Value="{Binding CalibratorCount}" IsSnapToTickEnabled="True"/>
    <TextBlock HorizontalAlignment="Left" Margin="165,42,0,0"
               TextWrapping="Wrap" Text="{Binding CalibratorCount}" VerticalAlignment="Top"/>
    <Label Content="Control Samples (max 4)" HorizontalAlignment="Left" Margin="10,62,0,0"
           VerticalAlignment="Top" FontStyle="Italic"/>
    <Slider HorizontalAlignment="Left" Margin="181,66,0,0"
            VerticalAlignment="Top" Cursor="Hand" Width="160" Maximum="4"
            Value="{Binding ControlCount}" IsSnapToTickEnabled="True"/>
    <TextBlock HorizontalAlignment="Left" Margin="165,68,0,0"
               TextWrapping="Wrap" Text="{Binding ControlCount}" VerticalAlignment="Top"/>
    <Label Content="Total Sample Preparations Selected:" HorizontalAlignment="Left"
           Margin="10,105,0,0" VerticalAlignment="Top" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock HorizontalAlignment="Left" Margin="225,110,0,0"
               FontWeight="Bold" FontStyle="Italic" Text="{Binding TotalPrepCount}"
               VerticalAlignment="Top"/>
  </Grid>
</Window>