2014-01-06 62 views
2

我有一個slider實施System.Windows.Controls.Slider使滑塊使用現有的IValueConverter

class MySlider : Slider 
{ 
    public MySlider() 
    { 
     Minimum = 1; 
     Maximum = 1000; 
    } 
} 

我用這樣的:MySlider slider = new MySlider() { Width = 400, Name = "TheSlider"};

它運作良好,但它是線性的。
我想使它非線性,因爲合理的值就像1,2,10,1000(例如)。
所以我定義了一個非線性IValueConverter這樣的:

public class LogScaleConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (int)Math.Log((int)value); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (int)Math.Exp((double)value); 
    } 
} 

問題:如何使滑塊使用本轉換器

+0

你有一個viewmodel? – thumbmunkeys

+0

@thumbmunkeys:不,只是MySlider,如上面的源代碼所示。 –

+0

值轉換器通常用於數據添加,而不是直接在控件中使用。如果您需要使其在沒有數據綁定的情況下工作,您可以將其他屬性添加到MySlider類中,例如'LogValue'。 – Clemens

回答

2

製作窗口資源作爲

<Window.Resources> 
    <local:LogScaleConverter x:Key="LogScaleConverterInstanse"/> 
    </Window.Resources> 

做一個文本框(或任何元素)<TextBox x:Name="firstName" />

綁定你的滑塊元素

<Slider Height="23" Name="slider1" Width="100" Value="{Binding Text,ElementName=  firstName,Converter={StaticResource LogScaleConverterInstanse}}"/> 
+0

我應該提到,我不使用XML定義,只是普通的C#代碼:'MySlider slider = new MySlider(){Width = 400,TheValue = 10}' –

+0

好吧使用像這樣綁定var slider = new MySlider ); var bnd = new Binding(「Text」){ElementName =「firstName」}; bnd.Converter = new LogScaleConverter(); slider.SetBinding(Slider.ValueProperty,bnd); – vijay22uk

1
var slider = new MySlider(); 
    var bnd = new Binding("Text") { ElementName = "firstName" }; 
    bnd.Converter = new LogScaleConverter(); 

    slider.SetBinding(Slider.ValueProperty, bnd); 
+0

什麼是「文本」和「名字」?我上面的代碼不包含這樣的變量名稱。 –

+0

firstName是其Text值滑塊綁定的TextBox的名稱。 – vijay22uk

+0

With'var bnd = new Binding();':'InvalidOperationException:雙向綁定需要Path或XPath' –

4

UPDATE:給你一個完整的工作代碼。

MainWindow.xaml

<StackPanel> 
    <StackPanel.Resources> 
     <spikes:LogScaleConverter x:Key="LogScaleConverter"/> 
    </StackPanel.Resources> 
    <TextBox x:Name="InputNumberTextBox" Width="100" Text="{Binding InputNumber, Mode=TwoWay}"/> 
    <Slider Width="1000" 
      Minimum="1" 
      Maximum="100" 
      Value="{Binding ElementName=InputNumberTextBox,Path=Text, Mode=TwoWay,Converter={StaticResource LogScaleConverter}}"/> 
</StackPanel> 

LogScaleConverter.cs現在

public class LogScaleConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var stringValue = value.ToString(); 
     if (string.IsNullOrWhiteSpace(stringValue)) return null; 

     var intValue = int.Parse(stringValue); 
     return Math.Log(intValue); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (int)Math.Exp((double)value); 
    } 
} 

注意,當你鍵入textbox的東西,它會改變滑塊的值基於你的公式。你可以在Convert上設置一個斷點,看看你是否真的想要在slider的值。

我不認爲有必要創建一個MySlider類,因爲您只設置了MinimumMaximum屬性,該屬性已在實際對象本身上可用。如果您要創建自定義內容,例如定義自己的Dependency Properties,則只應該擴展控件。

+0

我發佈了我的完整源代碼,並且它沒有「PropertyName」。你能否使用我的代碼中的變量名稱,或者修改我的代碼以包含它所屬的變量?非常感謝! –

+0

「PropertyName」只是一個佔位符。你實際上想在你的類中綁定到視圖的DataContext中的一個屬性 –

+0

對不起,但可以粘貼'public int SliderValue {get;組; }它在你的代碼中的位置?你可以把valueBinding代碼放在它所屬的位置嗎? (在我認爲的MainClass構造函數的末尾?)。非常感謝! –

2

我認爲你遇到的問題是每個人都假設(正確使用普通WPF的情況下)你的滑塊的值被綁定到其他控件(例如文本框)或ViewModel屬性。在這種常見情況下,轉換器在綁定中應用(查看所有其他答案)並將滑塊的內部線性值轉換爲對數值。

如果你只是用這一個基本的應用程序在您的代碼隱藏或其他應用程序代碼實際上只是輪詢滑塊控件直接,那麼你可以使用你的轉換器,例如:

var logConverter = new LogScaleConverter(); 
var logValue = logConverter.Convert(mySlider.Value, typeof(double), null, null); 

但我不得不說,這是沒有道理的,因爲你可以簡單地使用一種方法或將轉換放在你的代碼中。使用轉換器只有在您的用戶界面的其他位置綁定並且轉換器代碼可能發生更改時才使用該轉換器。

既然你無論如何都會做一個自定義的控制,另一種方法是將一個新的DependencyProperty添加到您的滑塊控件(也許稱之爲「LogSlider.LogValue」),其直接處理這個轉換:

public partial class LogSlider : Slider 
{ 
    public LogSlider() 
    { 
     InitializeComponent(); 


     var metadata = new FrameworkPropertyMetadata(); 
     metadata.PropertyChangedCallback += ValuePropertyChangedCallback; 
     ValueProperty.OverrideMetadata(typeof(LogSlider), metadata); 
    } 

    public double LogValue 
    { 
     get { return (double)GetValue(LogValueProperty);} 
     set { SetValue(LogValueProperty, (value));} 
    } 

    public static readonly DependencyProperty LogValueProperty = 
     DependencyProperty.Register("LogValue", typeof(double), typeof(LogSlider), new PropertyMetadata(0.0, LogValuePropertyChangedCallback)); 

    private static void LogValuePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) 
    { 
     dependencyObject.SetValue(ValueProperty, Math.Exp((double)args.NewValue)); 
    } 

    private static void ValuePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) 
    { 
     dependencyObject.SetValue(LogValueProperty, Math.Log((double)args.NewValue)); 
    } 
} 

現在您可以直接從您的自定義滑塊控件訪問LogValue,也可以在UI中雙向綁定LogValue - 線性值的更改會反映在日誌中,反之亦然。