我正在开发一个基本的WPF“Paint”应用程序项目。我有三个选项,绘制一个椭圆,绘制一条线,或绘制一个'形状'(填充封闭部分的线)。这三个选项用单选按钮表示。我有这个部分工作。这是一个示例屏幕截图:
http://i.stack.imgur.com/naPyI.jpg
基本上我现在需要做的是,当用户更改R,G,B和A(不透明度/ alpha)的滑块时,应该更新显示新颜色的小预览区域,并且该颜色应该是设置为线条或填充颜色,具体取决于更改的滑块组。 所有这些都需要通过数据绑定来完成。
我不确定是否能最好地解决这个问题。我应该为每个滑块(RGBA)设置单独的值,并将这些值传递给Color.FromArgb(R,G,B,A)??
编辑:这是我的代码
使用System; 使用System.Collections.Generic; 使用System.Linq; 使用System.Text; 使用System.Windows; 使用System.Windows.Controls; 使用System.Windows.Data; 使用System.Windows.Documents; 使用System.Windows.Input; 使用System.Windows.Media; 使用System.Windows.Media.Imaging; 使用System.Windows.Navigation; 使用System.Windows.Shapes; 使用System.ComponentModel;
namespace WpfPaint
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public bool start = false;
public Ellipse myEllipse;
public Polyline myLine;
public Line myRegLine = new Line();
public double xPos;
public double yPos;
public MainWindow()
{
InitializeComponent();
MyCanvas.Children.Add(myRegLine);
}
private void MyCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (this.ellipse.IsChecked ?? false)
{
if (start)
{
start = !start;
myEllipse = null;
}
else
{
start = true;
myEllipse = new Ellipse();
xPos = e.GetPosition(MyCanvas).X;
yPos = e.GetPosition(MyCanvas).Y;
MyCanvas.Children.Add(myEllipse);
myEllipse.StrokeThickness = 5;
if (comboBox2.Text == "Red")
{
myEllipse.Fill = Brushes.Red;
fillR.Value = 255;
fillG.Value = 0;
fillB.Value = 0;
}
else if (comboBox2.Text == "Green")
{
myEllipse.Fill = Brushes.Green;
fillR.Value = 0;
fillG.Value = 255;
fillB.Value = 0;
}
else if (comboBox2.Text == "Blue")
{
myEllipse.Fill = Brushes.Blue;
fillR.Value = 0;
fillG.Value = 0;
fillB.Value = 255;
}
if (comboBox1.Text == "Red")
{
myEllipse.Stroke = Brushes.Red;
lineR.Value = 255;
lineG.Value = 0;
lineB.Value = 0;
}
else if (comboBox1.Text == "Green")
{
myEllipse.Stroke = Brushes.Green;
lineR.Value = 0;
lineG.Value = 255;
lineB.Value = 0;
}
else if (comboBox1.Text == "Blue")
{
myEllipse.Stroke = Brushes.Blue;
lineR.Value = 0;
lineG.Value = 0;
lineB.Value = 255;
}
}
}
else
{
switch (e.ClickCount)
{
case 1:
if (myLine == null)
{
myLine = new Polyline();
MyCanvas.Children.Add(myLine);
myLine.StrokeThickness = 5;
if (comboBox1.Text == "Red")
{
myLine.Stroke = Brushes.Red;
lineR.Value = 255;
lineG.Value = 0;
lineB.Value = 0;
}
else if (comboBox1.Text == "Green")
{
myLine.Stroke = Brushes.Green;
lineR.Value = 0;
lineG.Value = 255;
lineB.Value = 0;
}
else if (comboBox1.Text == "Blue")
{
myLine.Stroke = Brushes.Blue;
lineR.Value = 0;
lineG.Value = 0;
lineB.Value = 255;
}
if (this.shape.IsChecked ?? false)
{
if (comboBox2.Text == "Red")
{
myLine.Fill = Brushes.Red;
fillR.Value = 255;
fillG.Value = 0;
fillB.Value = 0;
}
else if (comboBox2.Text == "Green")
{
myLine.Fill = Brushes.Green;
fillR.Value = 0;
fillG.Value = 255;
fillB.Value = 0;
}
else if (comboBox2.Text == "Blue")
{
myLine.Fill = Brushes.Blue;
fillR.Value = 0;
fillG.Value = 0;
fillB.Value = 255;
}
}
}
myLine.Points.Add(e.GetPosition(MyCanvas));
e.Handled = true;
break;
case 2:
myLine = null;
myRegLine = new Line();
MyCanvas.Children.Add(myRegLine);
break;
}
}
}
private void MyCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (start)
{
myEllipse.Height = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;
myEllipse.Width = Math.Abs(e.GetPosition(MyCanvas).X - xPos) * 2;
Canvas.SetTop(myEllipse, ((yPos) - myEllipse.Height / 2));
Canvas.SetLeft(myEllipse, ((xPos) - myEllipse.Width / 2));
}
else
{
if (myLine != null)
{
myRegLine.Stroke = myLine.Stroke;
myRegLine.X1 = myLine.Points.Last().X;
myRegLine.Y1 = myLine.Points.Last().Y;
myRegLine.X2 = e.GetPosition(MyCanvas).X;
myRegLine.Y2 = e.GetPosition(MyCanvas).Y;
}
}
}
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void comboBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
这是我的XAML
<Window x:Class="WpfPaint.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<RadioButton Content="Line" Height="16" HorizontalAlignment="Left" Margin="12,10,0,0" Name="line" GroupName="options" VerticalAlignment="Top" IsChecked="True" />
<RadioButton Content="Shape" Height="16" HorizontalAlignment="Left" Margin="12,34,0,0" Name="shape" GroupName="options" VerticalAlignment="Top" />
<RadioButton Content="Ellipse" Height="16" HorizontalAlignment="Left" Margin="12,56,0,0" Name="ellipse" GroupName="options" VerticalAlignment="Top" />
<Label Content="R" Margin="210,5,270,0" Height="31" VerticalAlignment="Top" />
<Slider Height="23" HorizontalAlignment="Left" Margin="229,5,0,0" Name="lineR" VerticalAlignment="Top" Width="50" IsMoveToPointEnabled="False" Interval="1" IsSelectionRangeEnabled="False" Maximum="255" />
<Slider Height="23" Margin="306,5,147,0" Name="lineG" VerticalAlignment="Top" IsMoveToPointEnabled="False" Interval="1" Maximum="255" />
<Label Content="G" Margin="282,3,203,0" Height="30" VerticalAlignment="Top" />
<Slider Height="23" HorizontalAlignment="Left" Margin="380,5,0,0" Name="lineB" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" />
<Label Content="B" Margin="358,3,129,280"/>
<Slider Height="23" HorizontalAlignment="Left" Margin="453,5,0,0" Name="lineA" VerticalAlignment="Top" Width="50" Interval="1" Maximum="255" Value="255" />
<Label Content="A" Margin="428,3,56,0" Height="28" VerticalAlignment="Top" />
<Canvas Name="MyCanvas" Background="#FFDADADA" Margin="0,76,0,0" PreviewMouseDown="MyCanvas_PreviewMouseDown" PreviewMouseMove="MyCanvas_PreviewMouseMove"></Canvas>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="127,5,0,0" Name="comboBox1" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox1_SelectionChanged">
<ComboBoxItem Content="Red" IsSelected="True" />
<ComboBoxItem Content="Green" />
<ComboBoxItem Content="Blue" />
</ComboBox>
<Label Content="Line" Height="28" HorizontalAlignment="Left" Margin="89,3,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="Fill" Height="28" HorizontalAlignment="Left" Margin="96,42,0,0" Name="label2" VerticalAlignment="Top" />
<ComboBox Height="23" HorizontalAlignment="Left" Margin="127,44,0,0" Name="comboBox2" VerticalAlignment="Top" Width="70" SelectionChanged="comboBox2_SelectionChanged">
<ComboBoxItem Content="Red" IsSelected="True" />
<ComboBoxItem Content="Green" />
<ComboBoxItem Content="Blue" />
</ComboBox>
<Label Content="R" Margin="210,42,270,238" />
<Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="229,44,0,0" Name="fillR" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
<Slider Height="23" HorizontalAlignment="Left" IsMoveToPointEnabled="False" Margin="306,44,0,0" Name="fillG" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
<Label Content="G" Margin="282,40,203,241" />
<Slider Height="23" HorizontalAlignment="Left" Margin="380,44,0,0" Name="fillB" VerticalAlignment="Top" Width="50" Maximum="255" Interval="1" />
<Label Content="B" Margin="358,42,0,241" HorizontalAlignment="Left" Width="16" />
<Slider Height="23" HorizontalAlignment="Left" Margin="453,44,0,0" Name="fillA" VerticalAlignment="Top" Width="50" Value="255" Interval="1" Maximum="255" />
<Label Content="A" Margin="428,42,56,241" />
</Grid>
答案 0 :(得分:1)
不确定这是否是最好的方法,但您可以在viewmodel中拥有5个公共属性: 一个用于Alpha,一个用于Red,一个用于Green,一个用于Blue,以及一个用户定义的结构,您将用它们将4个值“分组”在一起(我们称之为FillValue)。将4个滑块绑定为Alpha,红色,绿色和蓝色。在这4个属性的setter中,您在FillValue中设置相应的字段,然后为两个属性调用NotifyPropertyChanged。像这样:
public double Red
{
get { return FillValue.Red; }
set
{
FillValue.Red = value;
NotifyPropertyChanged("Red");
NotifyPropertyChanged("FillValue");
}
}
然后将预览的填充属性绑定到FillValue并添加转换器以将FillValue转换为画笔。绑定看起来像这样:
<StackPanel>
<StackPanel.Resources>
<RGBExample:FillValueCvtr x:Key="ColorCvtr"/>
</StackPanel.Resources>
<Rectangle Fill="{Binding FillValue, Converter={StaticResource ColorCvtr}}"/>
</StackPanel>